# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
> **Branch note (`active-uix`):** the legacy layers `src/lib/`, `src/uix/terra/`,
> `src/uix/air/` and the old `src/routes/` test tree were removed during the
> UIX refactor. The new ecosystem lives in `src/arts/`, `src/libs/`, `src/svrs/`,
> and `src/uix/{active-uix,soma,sema,eidos,morfo}`. Demos are being re-authored
> under `web/routes/` from scratch.
## Build / Test Commands
```bash
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
npm run dev # Start dev server (routes resolve from web/routes)
npm run build # Production build (static via adapter-static)
npm run test # Run all tests once
npm run test:unit # Run tests in watch mode
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
npx vitest run src/uix/morfo/compile.test.ts # Run a single test file
npx vitest run -t "describe name" # Run tests matching a pattern
npm run check # Type check with svelte-check
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
npm run lint # Check formatting (Prettier)
npm run format # Auto-format
```
## Code Style
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
- Tabs for indentation, single quotes, no trailing commas, 100 char print width (Prettier).
- Comments in **English** . (Some legacy Spanish comments remain — don't add new ones.)
- Svelte 5 runes mode is enforced globally (`svelte.config.js` `dynamicCompileOptions` ).
- DOM event handlers: lowercase (`onclick`, `onfocus` ). User callbacks: camelCase (`onComplete`, `onInteractOutside` ).
- State: `$state()` without `#` . Derived: `readonly x = $derived.by(...)` .
## Path Aliases
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
Aliases are kept in sync between `svelte.config.js` and `vite.config.ts` . Source
of truth is `vite.config.ts` (single `aliases` const reused by both top-level
resolve and the server-test project).
| Alias | Target |
| --- | --- |
| `@` | `src/` |
| `$active-app` , `$adom` , `$auth` , `$bus` , `$cache` , `$clipboard` , `$color` , `$connection` , `$format` , `$http` , `$langs` , `$logger` , `$motion` , `$orca` , `$perm` , `$prefs` , `$session` , `$sium` , `$storage` , `$timer` | `src/arts/{name}` |
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
| `$libs` , `$locale` , `$reactive` | `src/libs` , `src/libs/locale` , `src/libs/reactive` |
| `$svrs` | `src/svrs/` |
| `$uix` , `$active-uix` , `$soma` | `src/uix` , `src/uix/active-uix` , `src/uix/soma` |
## Vitest Two-Project Structure
`vite.config.ts` defines two test projects:
soma: dias date library, Calendar + RangeCalendar, Command fixes, doc updates
**Date library reorganisation** (no new third-party dependency)
- New `src/lib/util/dias/` with `_vendor/` (Adobe Apache 2.0 vendored code,
ATTRIBUTION.md preserved) and a public facade split into `types`,
`values`, `calendars`, `queries`, `operations`, `parse`, `format`,
`index`. Consumers import only from `$lib/util/dias`.
- All date-related `Intl` consolidated in `dias/format.ts` —
`DateFormatter`, cache, `resolveDateOrder`, `resolveHourCycle`,
placeholders, defaults.
- `ext/dates` now a thin reactive wrapper delegating to `dias`.
- Aligned App-layer `HourCycle` to canonical numeric form `12 | 24`
(matches `Intl.DateTimeFormat`'s `hour12`). Removed string form
`'12h' | '24h'` from `ext/app/types`, `ext/dates`,
`ext/presentation/locale-defaults`, and their tests.
- Repointed every consumer: `soma/external/dates`,
`terra/external/dates`, eight `routes/test/*` pages.
- Legacy `src/lib/util/dates/` left untouched by request.
**Tier 3 components**
- `soma/components/calendar/` — 14 parts, single + multiple selection,
`MonthSelect`/`YearSelect`, ISO/simple week numbers,
`isDateHoliday` matcher, `data-weekend` flag, navigation live-
region, RTL flip, full ARIA, 27-item checklist verified.
- `soma/components/range-calendar/` — 14 parts, range selection with
live hover preview (novel vs ark/bits/radix/react-aria), `minDays`
/ `maxDays` / `allowSingleDay`, third-click deselects only the
clicked endpoint.
- Test pages at `/test/soma/calendar` and `/test/soma/range-calendar`
with seven demos each. Links added to the soma index under a new
"Dates" section.
- READMEs with anatomy, parts, props, ARIA, keyboard, data-attrs, and
a competitive comparison table.
**Command fixes**
- Resolved O(N^2) reactive cascade: introduced
`visibleSet: $derived<Set<string>>` on the root provider;
per-item `isVisible` is now an O(1) `has()` lookup instead of
calling back into the provider, which was re-running all items'
derivations on every `itemsVersion` bump.
- Added `dir` prop with fallback to `soma.presentation.getDir()`;
horizontal arrows flip in RTL via `getDirectionalKeys`; root
receives `dir` attribute.
**Doc updates (session outcomes)**
- `CLAUDE.md`: replaced obsolete `@/glob/lib` date references with
`$lib/util/dias`; added canonical date-layer section; reinforced
`Provider` export rule and `data-{component}[-{part}]` naming
(never `data-soma-*`); clarified translation convention.
- `src/uix/soma/COMPONENT_GUIDE.md`: new checklist items 26
(component README required) and 27 (grep for data-attr
consistency); new Common Mistakes 11 (`data-soma-*` prefix), 12
(wrong date module), 13 (string `HourCycle`).
- `src/uix/soma/SOMA_ARCHITECTURE.md`: clarified data-attr naming
(canonical emitter is `createAttrs`; validator checks enum
values only, not names); new section covering date types and
formatting through `$soma/external/dates` → `$lib/util/dias`;
documented numeric `HourCycle`.
**Infrastructure**
- `PrimitiveHeaderAttributes` and `PrimitiveSelectAttributes` added
to `$soma/types`.
- `getLastFirstDayOfWeek`, `getNextLastDayOfWeek` re-exported from
`$soma/external/dates`.
- `calendar.*` and `range-calendar.*` translation blocks added to
`$soma/core/langs.ts`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
- **client**: Browser tests via Playwright for `*.svelte.{test,spec}.{js,ts}` .
- **server**: Node environment for `*.{test,spec}.{js,ts}` (excludes svelte tests).
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
## Architecture
The UIX is layered around a declarative contract (morfo) that the other layers
consume. Each consumer reads the morfo via `compileMorfo(morfo)` , never by
walking the raw declaration.
```
fix: address architectural audit findings + sync ecosystem docs
Audit: src/audit-opus-4-6-26.md. All non-words findings remediated.
Code:
- E1: navigation-menu indicator data-state visible -> open (render bug; the
active underline was permanently invisible). Clears the only invalid lint selector.
- SO1 + E2: raw `new ResizeObserver` -> ActiveDom.observeResize in carousel-provider
and the canvas-text useContainerWidth hook (+ s-text / s-text-virtual-list pass
eidos.dom). iframe/popup-safe, lifecycle-tracked.
- A1: defineUixServices now registers `motion`, so attach-mode app.motion is real
and the active-uix fallback becomes the true edge case (test guard updated).
- A2/A4: contracts.ts pins `motion` + `announce` in ActiveUixServiceContract +
publicSurface; dispose() comment corrected.
- SO2: carousel drops the hardcoded `transform 300ms ease-out` (the recipe already
handles it via [data-dragging]); also fixed the recipe's undefined `--duration-base`
token -> `--duration-slow` (it was masked by the inline).
- S1: HapticChannel reduced-motion via an injected ActiveDom port (mirrors
SoundChannelDom) instead of global matchMedia.
- T1: 10 sites repointed `$libs/dom` -> `$adom` (sema x5 + its tests x3, active-uix
value import, arts/prefs).
- M2 / S2 / S3: dead code removed (button `states:['idle','loading']`,
SemaRuntimeChannelId, SEMA_VALENCED_FAMILY_LIST).
Docs:
- Motion-as-service reflected across the ecosystem: CLAUDE.md (aliases + arch +
service note), arts/README, active_architecture, soma SOMA_ARCHITECTURE, eidos
README, eidos-motion.md.
- X1: CLAUDE.md "5 canonical channels" (false) -> the single canonical narrative
(8 book channels; Sema runs 2 + visual meta-channel, Eidos materializes 5).
- X2/X3/X4: sema/README (8 families + intentRequirement/intentGuidance split),
types.ts JSDoc (SEMA_INTENT_POLICY -> SEMA_FAMILY_POLICY), engine.ts cascade 6->5,
alias table ($frontend out, $lang->$langs, +$clipboard).
- E4: codex_audit.md HISTORICO banner.
Deferred: SU2 (test-only layering, not a build violation); Words M1/T5/E3 (WIP).
Verify: npm run check -> 1 pre-existing error (grafito), 0 new; sema 152/152,
contracts 31/32 (1 pre-existing words), carousel 4/4, motion 22/22.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4 months ago
arts/ → runtime artifacts: active-app, adom, motion, perm, prefs, ...
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
libs/ → pure helpers (zero-dep): reactive, days, dom, locale, ...
svrs/ → server-authoritative engines
uix/morfo → declarative contract: parts, data-attrs, ARIA, keyboard,
events with semantic family/intent. Compiler at compile.ts
emits CompiledMorfo (cached by WeakMap).
uix/sema → semantic engine + channels (visual / sound / vibra).
The visual channel writes data-event* during a hold window.
State attrs (data-state, data-disabled, ...) are NEVER
touched by sema — they belong to the morfo runtime.
uix/soma → headless component layer. Each provider consumes morfo +
sema via `runtime.trigger(eventName)` which sequences:
prewrite → semantic.emit → handler → effect-driven state attrs.
uix/eidos → CSS layer that selects against the data-attrs the morfo
contract promises. lint.ts validates a CSS file against
compileMorfo(morfo).contracts.cssSelectors.
uix/active-uix → composition root. Two boot modes:
- createActiveUix(options) — standalone (owns services)
- attachActiveUix(activeApp) — attach to external app
```
fix: address architectural audit findings + sync ecosystem docs
Audit: src/audit-opus-4-6-26.md. All non-words findings remediated.
Code:
- E1: navigation-menu indicator data-state visible -> open (render bug; the
active underline was permanently invisible). Clears the only invalid lint selector.
- SO1 + E2: raw `new ResizeObserver` -> ActiveDom.observeResize in carousel-provider
and the canvas-text useContainerWidth hook (+ s-text / s-text-virtual-list pass
eidos.dom). iframe/popup-safe, lifecycle-tracked.
- A1: defineUixServices now registers `motion`, so attach-mode app.motion is real
and the active-uix fallback becomes the true edge case (test guard updated).
- A2/A4: contracts.ts pins `motion` + `announce` in ActiveUixServiceContract +
publicSurface; dispose() comment corrected.
- SO2: carousel drops the hardcoded `transform 300ms ease-out` (the recipe already
handles it via [data-dragging]); also fixed the recipe's undefined `--duration-base`
token -> `--duration-slow` (it was masked by the inline).
- S1: HapticChannel reduced-motion via an injected ActiveDom port (mirrors
SoundChannelDom) instead of global matchMedia.
- T1: 10 sites repointed `$libs/dom` -> `$adom` (sema x5 + its tests x3, active-uix
value import, arts/prefs).
- M2 / S2 / S3: dead code removed (button `states:['idle','loading']`,
SemaRuntimeChannelId, SEMA_VALENCED_FAMILY_LIST).
Docs:
- Motion-as-service reflected across the ecosystem: CLAUDE.md (aliases + arch +
service note), arts/README, active_architecture, soma SOMA_ARCHITECTURE, eidos
README, eidos-motion.md.
- X1: CLAUDE.md "5 canonical channels" (false) -> the single canonical narrative
(8 book channels; Sema runs 2 + visual meta-channel, Eidos materializes 5).
- X2/X3/X4: sema/README (8 families + intentRequirement/intentGuidance split),
types.ts JSDoc (SEMA_INTENT_POLICY -> SEMA_FAMILY_POLICY), engine.ts cascade 6->5,
alias table ($frontend out, $lang->$langs, +$clipboard).
- E4: codex_audit.md HISTORICO banner.
Deferred: SU2 (test-only layering, not a build violation); Words M1/T5/E3 (WIP).
Verify: npm run check -> 1 pre-existing error (grafito), 0 new; sema 152/152,
contracts 31/32 (1 pre-existing words), carousel 4/4, motion 22/22.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4 months ago
**Motion** lives in `arts/motion` (`EngineMotion`, alias `$motion` ), exposed as
`uix.motion` and consumed by BOTH soma (`Presence.motion` → `motion.run` ) and
eidos (CSS generation + preset registration). It's an art — not part of eidos —
so soma can drive JS motion (spring) without a soma→eidos dependency. The DOM
arrives injected via a structural `MotionDom` port (`adom` satisfies it).
Two-moment model + F1– F7: `src/arts/motion/README.md` +
`src/uix/eidos/eidos-motion.md` .
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
### morfo (`src/uix/morfo/`)
soma: dias date library, Calendar + RangeCalendar, Command fixes, doc updates
**Date library reorganisation** (no new third-party dependency)
- New `src/lib/util/dias/` with `_vendor/` (Adobe Apache 2.0 vendored code,
ATTRIBUTION.md preserved) and a public facade split into `types`,
`values`, `calendars`, `queries`, `operations`, `parse`, `format`,
`index`. Consumers import only from `$lib/util/dias`.
- All date-related `Intl` consolidated in `dias/format.ts` —
`DateFormatter`, cache, `resolveDateOrder`, `resolveHourCycle`,
placeholders, defaults.
- `ext/dates` now a thin reactive wrapper delegating to `dias`.
- Aligned App-layer `HourCycle` to canonical numeric form `12 | 24`
(matches `Intl.DateTimeFormat`'s `hour12`). Removed string form
`'12h' | '24h'` from `ext/app/types`, `ext/dates`,
`ext/presentation/locale-defaults`, and their tests.
- Repointed every consumer: `soma/external/dates`,
`terra/external/dates`, eight `routes/test/*` pages.
- Legacy `src/lib/util/dates/` left untouched by request.
**Tier 3 components**
- `soma/components/calendar/` — 14 parts, single + multiple selection,
`MonthSelect`/`YearSelect`, ISO/simple week numbers,
`isDateHoliday` matcher, `data-weekend` flag, navigation live-
region, RTL flip, full ARIA, 27-item checklist verified.
- `soma/components/range-calendar/` — 14 parts, range selection with
live hover preview (novel vs ark/bits/radix/react-aria), `minDays`
/ `maxDays` / `allowSingleDay`, third-click deselects only the
clicked endpoint.
- Test pages at `/test/soma/calendar` and `/test/soma/range-calendar`
with seven demos each. Links added to the soma index under a new
"Dates" section.
- READMEs with anatomy, parts, props, ARIA, keyboard, data-attrs, and
a competitive comparison table.
**Command fixes**
- Resolved O(N^2) reactive cascade: introduced
`visibleSet: $derived<Set<string>>` on the root provider;
per-item `isVisible` is now an O(1) `has()` lookup instead of
calling back into the provider, which was re-running all items'
derivations on every `itemsVersion` bump.
- Added `dir` prop with fallback to `soma.presentation.getDir()`;
horizontal arrows flip in RTL via `getDirectionalKeys`; root
receives `dir` attribute.
**Doc updates (session outcomes)**
- `CLAUDE.md`: replaced obsolete `@/glob/lib` date references with
`$lib/util/dias`; added canonical date-layer section; reinforced
`Provider` export rule and `data-{component}[-{part}]` naming
(never `data-soma-*`); clarified translation convention.
- `src/uix/soma/COMPONENT_GUIDE.md`: new checklist items 26
(component README required) and 27 (grep for data-attr
consistency); new Common Mistakes 11 (`data-soma-*` prefix), 12
(wrong date module), 13 (string `HourCycle`).
- `src/uix/soma/SOMA_ARCHITECTURE.md`: clarified data-attr naming
(canonical emitter is `createAttrs`; validator checks enum
values only, not names); new section covering date types and
formatting through `$soma/external/dates` → `$lib/util/dias`;
documented numeric `HourCycle`.
**Infrastructure**
- `PrimitiveHeaderAttributes` and `PrimitiveSelectAttributes` added
to `$soma/types`.
- `getLastFirstDayOfWeek`, `getNextLastDayOfWeek` re-exported from
`$soma/external/dates`.
- `calendar.*` and `range-calendar.*` translation blocks added to
`$soma/core/langs.ts`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
Single source of truth for a component. A `Morfo` declares:
- `parts[]` — kebab + archetype + `data` + `aria` + optional `keyboard`
- `events[]` — name + `target` partRef + `semantic` + optional `prewrite` + `commits`
- `focus` — initial / trap / return / restore (for overlay components)
soma: dias date library, Calendar + RangeCalendar, Command fixes, doc updates
**Date library reorganisation** (no new third-party dependency)
- New `src/lib/util/dias/` with `_vendor/` (Adobe Apache 2.0 vendored code,
ATTRIBUTION.md preserved) and a public facade split into `types`,
`values`, `calendars`, `queries`, `operations`, `parse`, `format`,
`index`. Consumers import only from `$lib/util/dias`.
- All date-related `Intl` consolidated in `dias/format.ts` —
`DateFormatter`, cache, `resolveDateOrder`, `resolveHourCycle`,
placeholders, defaults.
- `ext/dates` now a thin reactive wrapper delegating to `dias`.
- Aligned App-layer `HourCycle` to canonical numeric form `12 | 24`
(matches `Intl.DateTimeFormat`'s `hour12`). Removed string form
`'12h' | '24h'` from `ext/app/types`, `ext/dates`,
`ext/presentation/locale-defaults`, and their tests.
- Repointed every consumer: `soma/external/dates`,
`terra/external/dates`, eight `routes/test/*` pages.
- Legacy `src/lib/util/dates/` left untouched by request.
**Tier 3 components**
- `soma/components/calendar/` — 14 parts, single + multiple selection,
`MonthSelect`/`YearSelect`, ISO/simple week numbers,
`isDateHoliday` matcher, `data-weekend` flag, navigation live-
region, RTL flip, full ARIA, 27-item checklist verified.
- `soma/components/range-calendar/` — 14 parts, range selection with
live hover preview (novel vs ark/bits/radix/react-aria), `minDays`
/ `maxDays` / `allowSingleDay`, third-click deselects only the
clicked endpoint.
- Test pages at `/test/soma/calendar` and `/test/soma/range-calendar`
with seven demos each. Links added to the soma index under a new
"Dates" section.
- READMEs with anatomy, parts, props, ARIA, keyboard, data-attrs, and
a competitive comparison table.
**Command fixes**
- Resolved O(N^2) reactive cascade: introduced
`visibleSet: $derived<Set<string>>` on the root provider;
per-item `isVisible` is now an O(1) `has()` lookup instead of
calling back into the provider, which was re-running all items'
derivations on every `itemsVersion` bump.
- Added `dir` prop with fallback to `soma.presentation.getDir()`;
horizontal arrows flip in RTL via `getDirectionalKeys`; root
receives `dir` attribute.
**Doc updates (session outcomes)**
- `CLAUDE.md`: replaced obsolete `@/glob/lib` date references with
`$lib/util/dias`; added canonical date-layer section; reinforced
`Provider` export rule and `data-{component}[-{part}]` naming
(never `data-soma-*`); clarified translation convention.
- `src/uix/soma/COMPONENT_GUIDE.md`: new checklist items 26
(component README required) and 27 (grep for data-attr
consistency); new Common Mistakes 11 (`data-soma-*` prefix), 12
(wrong date module), 13 (string `HourCycle`).
- `src/uix/soma/SOMA_ARCHITECTURE.md`: clarified data-attr naming
(canonical emitter is `createAttrs`; validator checks enum
values only, not names); new section covering date types and
formatting through `$soma/external/dates` → `$lib/util/dias`;
documented numeric `HourCycle`.
**Infrastructure**
- `PrimitiveHeaderAttributes` and `PrimitiveSelectAttributes` added
to `$soma/types`.
- `getLastFirstDayOfWeek`, `getNextLastDayOfWeek` re-exported from
`$soma/external/dates`.
- `calendar.*` and `range-calendar.*` translation blocks added to
`$soma/core/langs.ts`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
`compileMorfo(morfo)` returns a `CompiledMorfo` with pre-resolved `AttrPlan[]` ,
`KeyboardPlan[]` , `ActionPlan[]` , and `contracts.cssSelectors` (the closed set
of selectors eidos is allowed to use). Cached by morfo identity.
soma: dias date library, Calendar + RangeCalendar, Command fixes, doc updates
**Date library reorganisation** (no new third-party dependency)
- New `src/lib/util/dias/` with `_vendor/` (Adobe Apache 2.0 vendored code,
ATTRIBUTION.md preserved) and a public facade split into `types`,
`values`, `calendars`, `queries`, `operations`, `parse`, `format`,
`index`. Consumers import only from `$lib/util/dias`.
- All date-related `Intl` consolidated in `dias/format.ts` —
`DateFormatter`, cache, `resolveDateOrder`, `resolveHourCycle`,
placeholders, defaults.
- `ext/dates` now a thin reactive wrapper delegating to `dias`.
- Aligned App-layer `HourCycle` to canonical numeric form `12 | 24`
(matches `Intl.DateTimeFormat`'s `hour12`). Removed string form
`'12h' | '24h'` from `ext/app/types`, `ext/dates`,
`ext/presentation/locale-defaults`, and their tests.
- Repointed every consumer: `soma/external/dates`,
`terra/external/dates`, eight `routes/test/*` pages.
- Legacy `src/lib/util/dates/` left untouched by request.
**Tier 3 components**
- `soma/components/calendar/` — 14 parts, single + multiple selection,
`MonthSelect`/`YearSelect`, ISO/simple week numbers,
`isDateHoliday` matcher, `data-weekend` flag, navigation live-
region, RTL flip, full ARIA, 27-item checklist verified.
- `soma/components/range-calendar/` — 14 parts, range selection with
live hover preview (novel vs ark/bits/radix/react-aria), `minDays`
/ `maxDays` / `allowSingleDay`, third-click deselects only the
clicked endpoint.
- Test pages at `/test/soma/calendar` and `/test/soma/range-calendar`
with seven demos each. Links added to the soma index under a new
"Dates" section.
- READMEs with anatomy, parts, props, ARIA, keyboard, data-attrs, and
a competitive comparison table.
**Command fixes**
- Resolved O(N^2) reactive cascade: introduced
`visibleSet: $derived<Set<string>>` on the root provider;
per-item `isVisible` is now an O(1) `has()` lookup instead of
calling back into the provider, which was re-running all items'
derivations on every `itemsVersion` bump.
- Added `dir` prop with fallback to `soma.presentation.getDir()`;
horizontal arrows flip in RTL via `getDirectionalKeys`; root
receives `dir` attribute.
**Doc updates (session outcomes)**
- `CLAUDE.md`: replaced obsolete `@/glob/lib` date references with
`$lib/util/dias`; added canonical date-layer section; reinforced
`Provider` export rule and `data-{component}[-{part}]` naming
(never `data-soma-*`); clarified translation convention.
- `src/uix/soma/COMPONENT_GUIDE.md`: new checklist items 26
(component README required) and 27 (grep for data-attr
consistency); new Common Mistakes 11 (`data-soma-*` prefix), 12
(wrong date module), 13 (string `HourCycle`).
- `src/uix/soma/SOMA_ARCHITECTURE.md`: clarified data-attr naming
(canonical emitter is `createAttrs`; validator checks enum
values only, not names); new section covering date types and
formatting through `$soma/external/dates` → `$lib/util/dias`;
documented numeric `HourCycle`.
**Infrastructure**
- `PrimitiveHeaderAttributes` and `PrimitiveSelectAttributes` added
to `$soma/types`.
- `getLastFirstDayOfWeek`, `getNextLastDayOfWeek` re-exported from
`$soma/external/dates`.
- `calendar.*` and `range-calendar.*` translation blocks added to
`$soma/core/langs.ts`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
### eidos linter
soma: dias date library, Calendar + RangeCalendar, Command fixes, doc updates
**Date library reorganisation** (no new third-party dependency)
- New `src/lib/util/dias/` with `_vendor/` (Adobe Apache 2.0 vendored code,
ATTRIBUTION.md preserved) and a public facade split into `types`,
`values`, `calendars`, `queries`, `operations`, `parse`, `format`,
`index`. Consumers import only from `$lib/util/dias`.
- All date-related `Intl` consolidated in `dias/format.ts` —
`DateFormatter`, cache, `resolveDateOrder`, `resolveHourCycle`,
placeholders, defaults.
- `ext/dates` now a thin reactive wrapper delegating to `dias`.
- Aligned App-layer `HourCycle` to canonical numeric form `12 | 24`
(matches `Intl.DateTimeFormat`'s `hour12`). Removed string form
`'12h' | '24h'` from `ext/app/types`, `ext/dates`,
`ext/presentation/locale-defaults`, and their tests.
- Repointed every consumer: `soma/external/dates`,
`terra/external/dates`, eight `routes/test/*` pages.
- Legacy `src/lib/util/dates/` left untouched by request.
**Tier 3 components**
- `soma/components/calendar/` — 14 parts, single + multiple selection,
`MonthSelect`/`YearSelect`, ISO/simple week numbers,
`isDateHoliday` matcher, `data-weekend` flag, navigation live-
region, RTL flip, full ARIA, 27-item checklist verified.
- `soma/components/range-calendar/` — 14 parts, range selection with
live hover preview (novel vs ark/bits/radix/react-aria), `minDays`
/ `maxDays` / `allowSingleDay`, third-click deselects only the
clicked endpoint.
- Test pages at `/test/soma/calendar` and `/test/soma/range-calendar`
with seven demos each. Links added to the soma index under a new
"Dates" section.
- READMEs with anatomy, parts, props, ARIA, keyboard, data-attrs, and
a competitive comparison table.
**Command fixes**
- Resolved O(N^2) reactive cascade: introduced
`visibleSet: $derived<Set<string>>` on the root provider;
per-item `isVisible` is now an O(1) `has()` lookup instead of
calling back into the provider, which was re-running all items'
derivations on every `itemsVersion` bump.
- Added `dir` prop with fallback to `soma.presentation.getDir()`;
horizontal arrows flip in RTL via `getDirectionalKeys`; root
receives `dir` attribute.
**Doc updates (session outcomes)**
- `CLAUDE.md`: replaced obsolete `@/glob/lib` date references with
`$lib/util/dias`; added canonical date-layer section; reinforced
`Provider` export rule and `data-{component}[-{part}]` naming
(never `data-soma-*`); clarified translation convention.
- `src/uix/soma/COMPONENT_GUIDE.md`: new checklist items 26
(component README required) and 27 (grep for data-attr
consistency); new Common Mistakes 11 (`data-soma-*` prefix), 12
(wrong date module), 13 (string `HourCycle`).
- `src/uix/soma/SOMA_ARCHITECTURE.md`: clarified data-attr naming
(canonical emitter is `createAttrs`; validator checks enum
values only, not names); new section covering date types and
formatting through `$soma/external/dates` → `$lib/util/dias`;
documented numeric `HourCycle`.
**Infrastructure**
- `PrimitiveHeaderAttributes` and `PrimitiveSelectAttributes` added
to `$soma/types`.
- `getLastFirstDayOfWeek`, `getNextLastDayOfWeek` re-exported from
`$soma/external/dates`.
- `calendar.*` and `range-calendar.*` translation blocks added to
`$soma/core/langs.ts`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
`scripts/eidos-lint.ts <component>` and `scripts/eidos-lint-all.ts` classify every
`[data-*]` selector in eidos CSS as morfo-backed / eidos-only / invalid. Use
this to detect drift between the morfo contract and the eidos rules.
## Key Conventions
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
- **Never modify the morfo declaration files** without updating the eidos
selectors and provider sources that depend on them.
- **Read before acting.** When told to read a file, read it. Don't paraphrase.
- **Verify before reporting done.** Run `npm run check` and the relevant
vitest scope. UI claims need a browser check; if you can't run a browser, say so.
- **No backward-compat shims** when relocating code. Update consumers and delete
the old path; don't leave a re-export.
- **No re-export façades** between layers (e.g. soma must not re-export dias —
consume `$libs/days` directly).
- **Provider naming**: child providers reference the parent as `provider` , never
`root` . The exported component is `<Xxx.Provider>` . `createAttrs` still uses
the part kebab `'provider'` internally.
- **Data-attr naming**: `data-{component}` (provider) and `data-{component}-{kebab}`
(sub-parts). Never `data-soma-*` . The compiler emits these via
`compiled.parts.attrs` ; runtime queries match exactly.
- **CSS token naming (eidos recipes)**: bare-prefixed by component, never
by layer. Public tokens: `--{component}-…` (e.g. `--dialog-content-bg` ,
`--toggle-radius-md` ). Internal recipe tokens: `--_{component}-…` .
Never `--eidos-…` , `--air-…` , `--terra-…` , `--soma-…` . Migrating
`air-` baselines means stripping the `air-` prefix, not replacing it.
- **DOM helpers**: `$adom` is the single public surface for DOM-related
functionality at component / soma level. It re-exports all of
`$libs/dom` wholesale, plus the reactive `createActiveDom` runtime
and stateful primitives (`BodyScrollLock`, `DOMContext` , `RovingFocusGroup` ).
Components and soma NEVER import from `$libs/dom` directly —
consume `$adom` . Only `arts/adom/*` (the implementation), `arts/frontend`
(peer service fallback), and tests of `$libs/dom` may reach into it.
This includes responsive types (`ResponsiveProp< T > `, `Breakpoint` ,
`Breakpoints` ) — they travel with the runtime, so they live in `$adom` .
- **Iframe / popup correctness**: when you have a `uix.dom` , prefer
`uix.dom.getDocument(node?)` and `uix.dom.getWindow(node?)` over the
bare functions of the same name. The instance methods respect the
active-dom's `targetWindow` ; the bare functions fall back to the
global `document` / `window` , which is wrong in iframe / popup /
happy-dom-test contexts.
soma: dias date library, Calendar + RangeCalendar, Command fixes, doc updates
**Date library reorganisation** (no new third-party dependency)
- New `src/lib/util/dias/` with `_vendor/` (Adobe Apache 2.0 vendored code,
ATTRIBUTION.md preserved) and a public facade split into `types`,
`values`, `calendars`, `queries`, `operations`, `parse`, `format`,
`index`. Consumers import only from `$lib/util/dias`.
- All date-related `Intl` consolidated in `dias/format.ts` —
`DateFormatter`, cache, `resolveDateOrder`, `resolveHourCycle`,
placeholders, defaults.
- `ext/dates` now a thin reactive wrapper delegating to `dias`.
- Aligned App-layer `HourCycle` to canonical numeric form `12 | 24`
(matches `Intl.DateTimeFormat`'s `hour12`). Removed string form
`'12h' | '24h'` from `ext/app/types`, `ext/dates`,
`ext/presentation/locale-defaults`, and their tests.
- Repointed every consumer: `soma/external/dates`,
`terra/external/dates`, eight `routes/test/*` pages.
- Legacy `src/lib/util/dates/` left untouched by request.
**Tier 3 components**
- `soma/components/calendar/` — 14 parts, single + multiple selection,
`MonthSelect`/`YearSelect`, ISO/simple week numbers,
`isDateHoliday` matcher, `data-weekend` flag, navigation live-
region, RTL flip, full ARIA, 27-item checklist verified.
- `soma/components/range-calendar/` — 14 parts, range selection with
live hover preview (novel vs ark/bits/radix/react-aria), `minDays`
/ `maxDays` / `allowSingleDay`, third-click deselects only the
clicked endpoint.
- Test pages at `/test/soma/calendar` and `/test/soma/range-calendar`
with seven demos each. Links added to the soma index under a new
"Dates" section.
- READMEs with anatomy, parts, props, ARIA, keyboard, data-attrs, and
a competitive comparison table.
**Command fixes**
- Resolved O(N^2) reactive cascade: introduced
`visibleSet: $derived<Set<string>>` on the root provider;
per-item `isVisible` is now an O(1) `has()` lookup instead of
calling back into the provider, which was re-running all items'
derivations on every `itemsVersion` bump.
- Added `dir` prop with fallback to `soma.presentation.getDir()`;
horizontal arrows flip in RTL via `getDirectionalKeys`; root
receives `dir` attribute.
**Doc updates (session outcomes)**
- `CLAUDE.md`: replaced obsolete `@/glob/lib` date references with
`$lib/util/dias`; added canonical date-layer section; reinforced
`Provider` export rule and `data-{component}[-{part}]` naming
(never `data-soma-*`); clarified translation convention.
- `src/uix/soma/COMPONENT_GUIDE.md`: new checklist items 26
(component README required) and 27 (grep for data-attr
consistency); new Common Mistakes 11 (`data-soma-*` prefix), 12
(wrong date module), 13 (string `HourCycle`).
- `src/uix/soma/SOMA_ARCHITECTURE.md`: clarified data-attr naming
(canonical emitter is `createAttrs`; validator checks enum
values only, not names); new section covering date types and
formatting through `$soma/external/dates` → `$lib/util/dias`;
documented numeric `HourCycle`.
**Infrastructure**
- `PrimitiveHeaderAttributes` and `PrimitiveSelectAttributes` added
to `$soma/types`.
- `getLastFirstDayOfWeek`, `getNextLastDayOfWeek` re-exported from
`$soma/external/dates`.
- `calendar.*` and `range-calendar.*` translation blocks added to
`$soma/core/langs.ts`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
## Critical Rules
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
- **NEVER delete files without explicit instruction** ("delete", "remove",
"borra", "elimina"). If ambiguous, ASK first.
- **NEVER create fake translators / mocked services** in tests for components.
Use real instances composed via `createActiveUix` or `attachActiveUix` .
- **NEVER skip hooks (`--no-verify`) or bypass signing** unless explicitly asked.
If a hook fails, fix the root cause.
- **`$reactive` survives, `$lib` does not.** The `$reactive` alias points to the
current `src/libs/reactive` ; the singular `$lib` alias was removed in the
cleanup phase and any code that resurfaces it is a regression.
docs: prune obsolete audits + studies, refresh remaining references
Deleted 60 obsolete documents that no longer reflect the active-uix
state:
- 47 per-component audit logs (*-audit.md, audit_N.md, AUDIT.md)
- 5 global soma audits (AUDIT_1, codex_audit, soma-audit-04-20/21,
audit-prompt template)
- 5 closed studies (soma/study, morfo/study, morfo/DESIGN, morfo/
PROVIDER_STUDY_2026-04-23, uix/CONTINUITY_2026-04-24)
- 2 superseded refactor proposals (refactor_claude, refactor_code)
- 1 stale bug log (form/BUG-onchange-onblur-hang — repro path
src/routes/test/sium/kitchen-sink no longer exists)
Updated the remaining operational references to drop dead links and
reflect the post-cleanup architecture:
- src/uix/README.md — rewritten links section, dropped pointers to
terra/air/CONTINUITY/refactor docs, updated adom/dom paths
- src/uix/active_architecture.md — header now dated 2026-05-08, lists
the major shifts since 2026-04-26 (provider inheritance dropped,
eidos in production, doctrina parte IV, sound eager-init); pendings
section reflects the eidos migration roadmap; "see also" purged of
deleted files
- src/uix/morfo/README.md — file tree updated (removed DESIGN/study,
added compile/runtime/PERMUTATION_RUNNER); see-also pruned
- src/uix/sema/README.md — SoundChannel section now describes the
eager-init pattern (constructor-time, not lazy); pointer to
sema-implementation-guide added
- src/uix/soma/README.md — drops terra/air mentions, declares the
actual dependency direction (eidos -> soma, not the reverse)
- src/uix/soma/SOMA_ARCHITECTURE.md — §15 rewritten as "Estado actual
y deuda histórica" reflecting Provider-inheritance-drop; demo path
updated to web/routes/
- src/uix/soma/COMPONENT_GUIDE.md — A23 dates section now points to
$libs/days (no external/dates façade); demo paths swapped from
/test/soma/* to web/routes/
- src/uix/morfo/PERMUTATION_RUNNER.md — paths swapped to web/routes/
with a relocation note
- CLAUDE.md — Refactor Documents section replaced with Reference
Documents pointing to per-layer READMEs
npm run check holds at baseline (39 pre-existing errors, none new).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
## Reference Documents
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
docs: prune obsolete audits + studies, refresh remaining references
Deleted 60 obsolete documents that no longer reflect the active-uix
state:
- 47 per-component audit logs (*-audit.md, audit_N.md, AUDIT.md)
- 5 global soma audits (AUDIT_1, codex_audit, soma-audit-04-20/21,
audit-prompt template)
- 5 closed studies (soma/study, morfo/study, morfo/DESIGN, morfo/
PROVIDER_STUDY_2026-04-23, uix/CONTINUITY_2026-04-24)
- 2 superseded refactor proposals (refactor_claude, refactor_code)
- 1 stale bug log (form/BUG-onchange-onblur-hang — repro path
src/routes/test/sium/kitchen-sink no longer exists)
Updated the remaining operational references to drop dead links and
reflect the post-cleanup architecture:
- src/uix/README.md — rewritten links section, dropped pointers to
terra/air/CONTINUITY/refactor docs, updated adom/dom paths
- src/uix/active_architecture.md — header now dated 2026-05-08, lists
the major shifts since 2026-04-26 (provider inheritance dropped,
eidos in production, doctrina parte IV, sound eager-init); pendings
section reflects the eidos migration roadmap; "see also" purged of
deleted files
- src/uix/morfo/README.md — file tree updated (removed DESIGN/study,
added compile/runtime/PERMUTATION_RUNNER); see-also pruned
- src/uix/sema/README.md — SoundChannel section now describes the
eager-init pattern (constructor-time, not lazy); pointer to
sema-implementation-guide added
- src/uix/soma/README.md — drops terra/air mentions, declares the
actual dependency direction (eidos -> soma, not the reverse)
- src/uix/soma/SOMA_ARCHITECTURE.md — §15 rewritten as "Estado actual
y deuda histórica" reflecting Provider-inheritance-drop; demo path
updated to web/routes/
- src/uix/soma/COMPONENT_GUIDE.md — A23 dates section now points to
$libs/days (no external/dates façade); demo paths swapped from
/test/soma/* to web/routes/
- src/uix/morfo/PERMUTATION_RUNNER.md — paths swapped to web/routes/
with a relocation note
- CLAUDE.md — Refactor Documents section replaced with Reference
Documents pointing to per-layer READMEs
npm run check holds at baseline (39 pre-existing errors, none new).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
Architecture overview and motivations: [`src/uix/active_architecture.md` ](src/uix/active_architecture.md ).
Per-layer references:
- [`src/uix/morfo/README.md` ](src/uix/morfo/README.md )
- [`src/uix/sema/README.md` ](src/uix/sema/README.md )
- [`src/uix/soma/SOMA_ARCHITECTURE.md` ](src/uix/soma/SOMA_ARCHITECTURE.md ) +
[`src/uix/soma/COMPONENT_GUIDE.md` ](src/uix/soma/COMPONENT_GUIDE.md )
- [`src/uix/eidos/README.md` ](src/uix/eidos/README.md ) +
[`src/uix/eidos/components/README.md` ](src/uix/eidos/components/README.md )
soma: dias date library, Calendar + RangeCalendar, Command fixes, doc updates
**Date library reorganisation** (no new third-party dependency)
- New `src/lib/util/dias/` with `_vendor/` (Adobe Apache 2.0 vendored code,
ATTRIBUTION.md preserved) and a public facade split into `types`,
`values`, `calendars`, `queries`, `operations`, `parse`, `format`,
`index`. Consumers import only from `$lib/util/dias`.
- All date-related `Intl` consolidated in `dias/format.ts` —
`DateFormatter`, cache, `resolveDateOrder`, `resolveHourCycle`,
placeholders, defaults.
- `ext/dates` now a thin reactive wrapper delegating to `dias`.
- Aligned App-layer `HourCycle` to canonical numeric form `12 | 24`
(matches `Intl.DateTimeFormat`'s `hour12`). Removed string form
`'12h' | '24h'` from `ext/app/types`, `ext/dates`,
`ext/presentation/locale-defaults`, and their tests.
- Repointed every consumer: `soma/external/dates`,
`terra/external/dates`, eight `routes/test/*` pages.
- Legacy `src/lib/util/dates/` left untouched by request.
**Tier 3 components**
- `soma/components/calendar/` — 14 parts, single + multiple selection,
`MonthSelect`/`YearSelect`, ISO/simple week numbers,
`isDateHoliday` matcher, `data-weekend` flag, navigation live-
region, RTL flip, full ARIA, 27-item checklist verified.
- `soma/components/range-calendar/` — 14 parts, range selection with
live hover preview (novel vs ark/bits/radix/react-aria), `minDays`
/ `maxDays` / `allowSingleDay`, third-click deselects only the
clicked endpoint.
- Test pages at `/test/soma/calendar` and `/test/soma/range-calendar`
with seven demos each. Links added to the soma index under a new
"Dates" section.
- READMEs with anatomy, parts, props, ARIA, keyboard, data-attrs, and
a competitive comparison table.
**Command fixes**
- Resolved O(N^2) reactive cascade: introduced
`visibleSet: $derived<Set<string>>` on the root provider;
per-item `isVisible` is now an O(1) `has()` lookup instead of
calling back into the provider, which was re-running all items'
derivations on every `itemsVersion` bump.
- Added `dir` prop with fallback to `soma.presentation.getDir()`;
horizontal arrows flip in RTL via `getDirectionalKeys`; root
receives `dir` attribute.
**Doc updates (session outcomes)**
- `CLAUDE.md`: replaced obsolete `@/glob/lib` date references with
`$lib/util/dias`; added canonical date-layer section; reinforced
`Provider` export rule and `data-{component}[-{part}]` naming
(never `data-soma-*`); clarified translation convention.
- `src/uix/soma/COMPONENT_GUIDE.md`: new checklist items 26
(component README required) and 27 (grep for data-attr
consistency); new Common Mistakes 11 (`data-soma-*` prefix), 12
(wrong date module), 13 (string `HourCycle`).
- `src/uix/soma/SOMA_ARCHITECTURE.md`: clarified data-attr naming
(canonical emitter is `createAttrs`; validator checks enum
values only, not names); new section covering date types and
formatting through `$soma/external/dates` → `$lib/util/dias`;
documented numeric `HourCycle`.
**Infrastructure**
- `PrimitiveHeaderAttributes` and `PrimitiveSelectAttributes` added
to `$soma/types`.
- `getLastFirstDayOfWeek`, `getNextLastDayOfWeek` re-exported from
`$soma/external/dates`.
- `calendar.*` and `range-calendar.*` translation blocks added to
`$soma/core/langs.ts`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
docs + switch: align active docs to canon, migrate switch to eidos wrapper
Phase 4 (docs alignment with the canonical guide):
- active_architecture.md — Dialog example refactored to the new event
shape (target inside semantic, explicit verb + sequence). Verbs
table grouped by family with the post-canon vocabulary (select/
toggle moved to commit, edit removed from handle, new verbs added).
Section 10 (Estado actual) updated to 2026-05-08 with current
progress: doctrina cerrada, eidos en producción, SoundChannel
eager-init, switch migrated, etc. "Para profundizar" §14 points at
the canonical guide.
- morfo/README.md — Step 5.5 added covering the doctrinal event
shape with all fields (semantic.family, .verb, .target, .sequence,
.intent) and the two naming shapes ({verb}-{variant} and
{family}-{verb}).
- sema/README.md — verbs section restructured to Record-by-family
matching the runtime; documents the verbs that moved between
families per the canon. Naming shapes section updated with both
forms and validateEventName signature.
- CLAUDE.md — "Session hand-off" rewritten with the post-canon
state. Pointer at GUIA_IMPLEMENTACION_SEMAUIX.md as the canonical
source. Pending list refreshed: switch is the immediate next
component, persistence/a11ySemantic/polymorphism deferred until
real consumers appear.
Switch migration to the eidos wrapper pattern:
- morfo/components/switch.ts — adds events: [{ commit-toggle }] with
the doctrinal shape (verb=toggle, sequence=post, intent fromProp
binding to the 4 supported intents). New data-* (data-color with
the 6-token Toggle/Switch subset, data-readonly, data-invalid,
data-required) and corresponding aria-*. scope expanded to
['soma', 'sema'].
- soma/components/switch/types.ts — adds intent, color, readonly,
invalid, aria-labelledby props with full JSDoc. Subset constrained
per guide §3.1 (Toggle/Switch row).
- soma/components/switch/switch-provider.svelte.ts — runtime-direct,
Field integration via FieldProvider.get(), isDisabled/isReadonly/
isRequired/isInvalid OR-merge derivations, intent ↔ color
resolution (intent wins when evaluative), runtime.trigger(
'commit-toggle') in onclick.
- soma/components/switch/components/switch.svelte — wires the new
props through bindProps.
- eidos/components/switch/{switch.css, switch.svelte, types.ts,
index.ts, README.md} — full subdirectory pattern, mirroring
toggle. Recipe drops legacy success/warning/danger/info selectors;
declares the 6 doctrinal data-color values directly. Wrapper
auto-renders Switch.Thumb inside the track and exposes an optional
`thumb` snippet for in-thumb glyphs.
- eidos/components/switch.css (legacy flat) deleted; eidos/index.css
updated to import the subdirectory recipe.
- web/routes/switch/+page.svelte — interactive testbed with all soma
props as live controls + tabs (Live, Soma, Morfo, Sema, Eidos,
Notes). Mirrors toggle's structure.
npm run check holds at the 39-error baseline. Tests 217/217 green.
Pending:
- Migrate collapsible / dialog / drawer / popover / toast / avatar
to the eidos wrapper pattern.
- Persistence + holds-by-intent — defer until first signal.warn /
signal.alert consumer.
- a11ySemantic + polymorphic events — defer until concrete need.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
The canonical guide for sema vocabulary, morfo event shape, color
tokens, persistence and a11ySemantic lives in
[`src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md` ](src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md ).
That document is authoritative — when in doubt about families, intents,
verbs, color subsets per component, or holds, that's the source.
## Sema cascade selectors must use the typed builder
Cascade rules in `src/uix/sema/components/*.ts` MUST construct their
`selector` via `semaSelector(morfo, partKebab, matchers?)` from
`$uix/morfo` . **Never hand-write selector strings** that target morfo-
emitted attrs (`[data-{component}]`, `[data-{component}-{part}]` ,
`[data-event="..."]` ). The helper:
- Compile-error if `partKebab` doesn't exist on `morfo.parts` .
- Compile-error if `matchers.eventName` doesn't match `morfo.events` .
- Type-checks `eventFamily` /`eventIntent` against the canonical sema
unions.
- Output is the same CSS string the cascade rule needs — zero runtime
cost beyond concatenation.
Hand-written selectors in cascade rules are an architecture violation:
when morfo renames a part or event, the strings go stale silently. The
helper wires the cascade to the morfo's contract so renames break at
the type level.
```ts
// good
import { semaSelector } from '$uix/morfo'
import { dialogMorfo } from '$uix/morfo/components/dialog'
{
selector: semaSelector(dialogMorfo, 'content', { eventFamily: 'commit' }),
haptic: { kind: 'tap' }
}
// bad — string drifts silently if morfo renames
{
selector: '[data-dialog-content][data-event-family="commit"]',
haptic: { kind: 'tap' }
}
```
## Sema: intent policy per family
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: { 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' }
}
```
- **`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 `intentRequirement` . Editing the const reshapes the discriminated union.
Runtime enforcement: `validateSemaEvent` throws when an `intentRequirement: 'required'` family declares an event without intent. Optional families pass silently.
**`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
fix: address architectural audit findings + sync ecosystem docs
Audit: src/audit-opus-4-6-26.md. All non-words findings remediated.
Code:
- E1: navigation-menu indicator data-state visible -> open (render bug; the
active underline was permanently invisible). Clears the only invalid lint selector.
- SO1 + E2: raw `new ResizeObserver` -> ActiveDom.observeResize in carousel-provider
and the canvas-text useContainerWidth hook (+ s-text / s-text-virtual-list pass
eidos.dom). iframe/popup-safe, lifecycle-tracked.
- A1: defineUixServices now registers `motion`, so attach-mode app.motion is real
and the active-uix fallback becomes the true edge case (test guard updated).
- A2/A4: contracts.ts pins `motion` + `announce` in ActiveUixServiceContract +
publicSurface; dispose() comment corrected.
- SO2: carousel drops the hardcoded `transform 300ms ease-out` (the recipe already
handles it via [data-dragging]); also fixed the recipe's undefined `--duration-base`
token -> `--duration-slow` (it was masked by the inline).
- S1: HapticChannel reduced-motion via an injected ActiveDom port (mirrors
SoundChannelDom) instead of global matchMedia.
- T1: 10 sites repointed `$libs/dom` -> `$adom` (sema x5 + its tests x3, active-uix
value import, arts/prefs).
- M2 / S2 / S3: dead code removed (button `states:['idle','loading']`,
SemaRuntimeChannelId, SEMA_VALENCED_FAMILY_LIST).
Docs:
- Motion-as-service reflected across the ecosystem: CLAUDE.md (aliases + arch +
service note), arts/README, active_architecture, soma SOMA_ARCHITECTURE, eidos
README, eidos-motion.md.
- X1: CLAUDE.md "5 canonical channels" (false) -> the single canonical narrative
(8 book channels; Sema runs 2 + visual meta-channel, Eidos materializes 5).
- X2/X3/X4: sema/README (8 families + intentRequirement/intentGuidance split),
types.ts JSDoc (SEMA_INTENT_POLICY -> SEMA_FAMILY_POLICY), engine.ts cascade 6->5,
alias table ($frontend out, $lang->$langs, +$clipboard).
- E4: codex_audit.md HISTORICO banner.
Deferred: SU2 (test-only layering, not a build violation); Words M1/T5/E3 (WIP).
Verify: npm run check -> 1 pre-existing error (grafito), 0 new; sema 152/152,
contracts 31/32 (1 pre-existing words), carousel 4/4, motion 22/22.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4 months ago
The perceptual layer is **NOT closed** . The book defines **8 expression
channels** (time · motion · presence · depth · shape · color · sound · haptic);
the framework SPLITS them by owner — and this is the single canonical narrative:
- **Sema executes 2 runtime channels** — `sound` + `haptic` , the ONLY two
declared in `SemaChannelSignatures` — plus projects the `visual` meta-channel
(it stamps `data-event-*` during the hold). `motion` /`color`/`presence` were
explicitly removed from sema (`sema-map.ts`); the engine knows no DOM/CSS.
- **Eidos materializes the visual channels** (motion / presence / depth / shape /
color) by reacting in CSS to those `data-event-*` + the morfo's
`data-state` /`data-intent`. Eidos is the sole visual owner.
Apps add more *sema* channels (a11y, voice, …) via TypeScript declaration
merging of `SemaChannelSignatures` .
**The semantic tokens are `data-event-*` **: the engine stamps `data-event` ,
`data-event-family` , `data-event-intent` , `data-event-phase` , `data-event-id`
on `signal.target` BEFORE the cascade resolves. Cascade rules use CSS
selectors that target those tokens directly — same surface that eidos CSS
already reads. Engine owns stamp/unstamp; VisualChannel only owns the hold.
Cascade rules are **flat** (no `overrides: { eventLabel: ... }` middle
layer): a single selector + per-channel deltas, like a CSS rule.
```ts
{
selector: '[data-dialog-content][data-event-intent="threat"]',
sound: { sampleUrl: '/sounds/dialog-fail.wav' },
haptic: { kind: 'error', pattern: [50, 80, 50, 80, 50] }
}
```
Resolution cascade (each layer overrides the previous):
```
1. SEMA_MAP.families[F].base — per-channel signatures
2. SEMA_MAP.intents[I].deltas — valenced families only;
numbers ADD (modificadores)
3. signal.overrides + signal.channels — per-event morfo overrides;
numbers REPLACE
4. engineOpts.overrides.runtime — path-based globals; REPLACE
5a. engineOpts.components[].cascade — per-component packs
(sema/components/{name}.ts)
5b. engineOpts.overrides.cascade — app-level rules; appended
AFTER packs so they win
on equal specificity
```
**Per-component packs live in `src/uix/sema/components/{name}.ts` ** —
symmetric to morfo / soma / eidos. Each exports a `Sema` with
`cascade` rules + optional `preloadSamples` (WAVs decoded at boot).
**Override semantics — numbers**:
- intent.deltas (capa 2): numbers ADD (modificadores compositivos).
- overrides (capas 4, 5, 6): numbers REPLACE (`color: red`, not "add red").
- Use `{ op: 'add' }` / `{ op: 'multiply' }` / `{ op: 'replace' }` for
explicit semantics either way.
**`intent.deltas` owns the perceptual signature of the intent** — the
sound primitives `pitch` , `gain` , `contour` (and the haptic `intensity`
when shaped per-intent) come from capa 2. **Cascade rules (capas 6a/6b)
MUST NOT override these primitives** — doing so flattens the perceptual
difference between `risk` / `threat` / `loss` (or `affirm` / `fulfill` ).
Cascade rules add character (`haptic.kind`, `haptic.pattern` ,
`sound.sampleUrl` , `motion.easing` , `presence.backdrop` ) — not the
intent's evaluative profile. If a per-component cascade rule needs to
*shift* a numeric primitive (e.g. close-* in emerge goes descending),
use `{ op: 'add', value: -150 }` so it composes on top of the intent
rather than erasing it.
`HapticChannel` (V1, real — Vibration API) is opt-in via
`new EngineSemantic({ haptic: true })` . Sound and haptic both default
off because they have audible / tactile side effects.
Canonical sources: `src/uix/sema/sema-map.ts` (SEMA_MAP value +
SemaChannelSignatures registry + Sema), `src/uix/sema/resolver.ts`
(cascade implementation + CSS specificity), `src/uix/sema/stamp.ts`
(stamp/unstamp), `src/uix/sema/components/*.ts` (per-component packs),
`src/uix/sema/README.md` .
## Eidos drift defense — types over lint
Selector drift between morfo's emitted attrs and the layers that style /
react to them (eidos CSS, sema cascade) is defended **at compile time
via typed builders**, not at lint time.
- **Sema cascade rules** (`sema/components/*.ts`) consume
`semaSelector(morfo, partKebab, matchers?)` from `$uix/morfo` . Renames
in morfo break the cascade at type-check time. See "Sema cascade
selectors must use the typed builder" above.
- **Eidos plain `.css` recipes** are still raw CSS today — there is no
CSS-side typed builder. For those, `scripts/eidos-lint.ts` remains as
an **opt-in safety net** that classifies each `[data-*]` selector as
`morfo-backed` / `eidos-only` / `invalid` . It is not the architectural
contract; the contract is the morfo declaration.
Rule: when a layer can consume the morfo via TypeScript (anything in
`.ts` / `.svelte` ), it MUST use the typed builder. Lint is for the
remaining surface (plain CSS recipes) until those gain a builder of
their own. Hand-written morfo-targeting selector strings in TypeScript
files are an architecture violation, not a lint warning.
## Session hand-off — 2026-05-27 (persistence + a11ySemantic + polymorphic)
Sprint cerrando los 3 ítems diferidos del hand-off 2026-05-08: persistence + holds-by-intent (libro §6), a11ySemantic per event (libro §9), polymorphic events (libro §5.3). Detalle completo en `src/docs/LIBRO_VARIACIONES_Y_EXTENSIONES.md` D.9 / D.10 / D.11.
**Persistence (libro §6.1)** — separa `hold` (duración perceptible mínima) de `persistence` (lifecycle real):
- Nuevo tipo `SignalPersistence = 'transient' | 'untilAction' | 'untilFix' | 'stateBound'` en `src/uix/sema/types.ts` , propagado a `SemanticSignal` , `MorfoEventSemantic` y `TriggerOptions` .
- Tabla canónica `SEMA_HOLDS_BY_INTENT` en `src/uix/sema/holds.ts` (referencia, NO auto-aplicada — default conservador `'transient'` ).
- `EngineSemantic.emit()` ahora devuelve `Promise<string>` (el id). Para `persistence !== 'transient'` mantiene la proyección viva pasado el hold; expone `engine.clear(id)` , `engine.clearTarget(target)` , `engine.hasActive(id)` .
- `SomaRuntime.trigger()` devuelve `TriggerResult { id?, persistence? }` . Expone `runtime.clearSignal(id)` , `runtime.clearTarget(target)` , `runtime.partRef(part)` (helper que devuelve el HTMLElement registrado de un part — útil para que providers limpien sin trackear ids).
- 6 morfos declaran `persistence` explícita: `announce.signal-alert` (untilAction), `dialog/drawer.close-after-fail` (transient explícito), `file-upload.signal-warn-reject` + `form.signal-warn-invalid` (untilFix), `password-field.signal-notify-caps-state` (stateBound).
- 3 providers cabledados con `clearTarget(provider)` : form (limpia al validar / reset), file-upload (limpia antes de cada nueva ronda de accept/reject + en remove / clear), password-field (limpia indicator al apagarse caps lock).
**a11ySemantic (libro §9.1)**:
- Nuevo `MorfoA11ySemantic` interface en `src/uix/morfo/types.ts` : `requiresPersistentTrace?` , `requiresLiveRegion?` , `requiresFocusMove?` , `keyboardEquivalent?` , `reducedMotionFallback?: 'state' | 'text' | 'focus' | 'none'` . Añadido como `a11ySemantic?` opcional en `MorfoEvent` . Pasa por compile a `ActionPlan.a11ySemantic` .
- Helper de reduced-motion en `src/arts/adom/reduced-motion.svelte.ts` (paralelo a `viewport.svelte.ts` ): `ReducedMotionTracker` reactivo del media query con SSR-safe fallback. Expuesto en `ActiveDom.prefersReducedMotion.matches` .
- `ActiveUix.announce(message, priority?, timeout?)` : live region compartida lazy-creada vía `dom.writeNode` . No depende de soma. Polite/assertive son regiones separadas, cleanup en `dispose()` .
- `Soma.runtime()` auto-wires `sources.announce = (m, p) => uix.announce(m, p)` . Tests usan fake `announce` .
- `SomaRuntime.trigger()` honra a11ySemantic después del emit: live region (con `opts.message` ), focus move, reduced-motion fallback (incluye forzar `channels: []` cuando fallback = 'state').
- 6 morfos anotados (los mismos consumidores).
**Polymorphic events (libro §5.3)** — ADITIVO sobre el shape concreto:
- Morfo declara `family` + `intent` + `verb` como default. Si añade `allowedFamilies: readonly SemaFamily[]` , los providers pueden override la family en `runtime.trigger(name, { semantic: { family, intent?, verb? } })` . El default family del morfo es IMPLÍCITAMENTE allowed.
- `isPolymorphicSemantic(semantic)` helper exportado de `$uix/morfo` .
- `SomaRuntimePolymorphicError` cuando override no está en allowedFamilies.
- Diseño aditivo (no variante separada con `defaultSemantic` ) elegido para mantener backwards-compat con 29 morfos existentes y demos que acceden `event.semantic.family` directamente.
**Tests**: 671/671 pasan en `src/uix/sema + morfo + soma + src/arts/adom/test` . 4 fallas pre-existentes en `src/uix/contracts.test.ts` (words component translation keys) — confirmadas en baseline antes de mis cambios via `git stash` .
**`npm run check`**: 1 error pre-existente en `src/uix/soma/components/command/command-provider.svelte.ts:384` (`Cannot find name 'attrs'`) que ya estaba en main.
**Pendientes deliberadamente fuera del sprint** (resueltos en la segunda mitad — ver hand-off 2026-05-27 #2 abajo):
- ~~Extender persistence a tags-input + textarea~~ — DONE
- ~~Caller messages para announce~~ — DONE (form / file-upload / password-field / dialog / drawer)
- ~~Demo polymorphic real~~ — DONE (Dialog refactorizado a polymorphic close)
## Session hand-off — 2026-05-27 #2 (messages + persistence ext + Dialog polymorphic)
Segunda mitad del sprint cerrando el backlog del hand-off anterior. 3 grupos de cambios.
**M — Caller messages para live region**:
Cada provider que dispara un evento con `a11ySemantic.requiresLiveRegion` ahora pasa `opts.message` con texto localizado. La live region (ya cabledada via `Soma.runtime() → sources.announce` ) finalmente anuncia algo:
- `form-provider` : `signal-warn-invalid` → "1 form error..." / "{N} form errors..." (count = `Object.keys(form.issues).length` ). Usa `FORM_LANGS.ERROR_SUMMARY_*` .
- `file-upload-provider` : `signal-warn-reject` → "1 file was rejected" / "{N} files were rejected". Nuevas entradas `FILE_UPLOAD_LANGS.REJECT_SUMMARY_SINGLE/MULTI` + langs catalog.
- `password-field-provider` : `signal-notify-caps-state` → "Caps Lock is on" (usa `PASSWORD_FIELD_LANGS.CAPS_WARNING` que ya existía).
- `dialog-provider.dismissWith(action, { message })` : signatura aceptando `message` opcional, forwarded al trigger.
- `drawer-provider.dismissWith(action, { message })` : igual que dialog.
**P — Persistence extendido a tags-input + textarea**:
Misma doctrina §6.2 — signal+risk = untilFix:
- `tags-input.signal-warn-reject` → persistence: `untilFix` + a11ySemantic + provider clear via `clearTarget(input)` . Nueva entrada `tags-input.reject-warning` en langs catalog. Provider gana método privado `emitWarnReject(target)` que centraliza clear + emit + message. Successful add también clearea (la adición VÁLIDA es el "fix" de un reject previo).
- `textarea.signal-warn-count-overflow` → persistence: `untilFix` + a11ySemantic + provider clear en transición OUT-of-overflow. Nueva entrada `textarea.overflow-warning` en langs catalog. Provider emite SOLO en transición INTO overflow (no en cada keystroke al cap) — el `untilFix` proyecta persistente, no necesita re-anuncio.
**POLY — Dialog refactor a polymorphic close**:
Caso real de uso del feature de eventos polymorphic (§5.3). 5 eventos `close-*` colapsados en 1 evento `close` :
- **Morfo** (`dialog.ts`): un evento `close` con `family: 'emerge', verb: 'close', allowedFamilies: ['emerge', 'commit', 'signal']` . SIN `prewrite` (el provider escribe `data-last-action` imperativamente).
- **Validador relajado**: el invariante "cada `values[]` debe ser prewritten por algún event" cayó al sentido único "cada prewrite con value debe estar en `values[]` ". Razón: con polymorphism los values pueden ser escritos imperativamente. El comentario en `schema.ts` explica.
- **Provider** (`dialog-provider.svelte.ts`): `DISMISS_CAUSES` mapa de acciones a `{ lastAction, semantic }` . `dismissWith(action, opts)` traduce a `dom.apply` + `runtime.trigger('close', { semantic, ... })` . `triggerClose` es privado ahora.
- **Cascade sema** (`sema/components/dialog.ts`): selectores `eventName: 'close-dismiss-outside'` → `eventName: 'close', state: { attr: 'data-last-action', value: 'dismissed-outside' }` . `eventNamePrefix: 'close-'` → `eventName: 'close', eventFamily: 'emerge'` .
- **Eidos CSS** (`dialog.css`): NO cambió — ya leía `data-last-action` para tintar, no nombres de evento.
- **API pública preservada**: consumidores externos no notan diferencia (`dismissWith` mantiene firma + comportamiento observable).
- **Drawer / Popover**: NO refactorizados. Mismo patrón aplicable; defer porque cada uno requiere reescribir su cascade + decisión separada de timing.
**Tests**:
- `npx vitest run src/uix/sema src/uix/morfo src/uix/soma src/arts/adom/test` : **679/679 pass** .
- `npm run check` : 1 error pre-existente (`command-provider.svelte.ts:384` — ya en baseline).
- 4 fallas pre-existentes en `src/uix/contracts.test.ts` (words translations) — no relacionadas.
**Pendientes a futuro** (cubierto en hand-off 2026-05-27 #3 abajo):
- ~~Refactor analógico de Drawer + Popover a polymorphic close~~ — DONE
- Otros `signal.warn-*` no incluidos: hay variantes con `verb: 'warn'` que podrían también beneficiarse de persistence untilFix (revisar caso por caso).
## Session hand-off — 2026-05-27 #3 (Drawer + Popover polymorphic close)
Tercera tanda del sprint — completa el rollout del patrón polymorphic close (book §5.3) a los dos componentes hermanos de Dialog. Mismo refactor aplicado de forma sistemática.
**Drawer**:
- Morfo: 5 close-* → 1 polymorphic `close` con `family: 'emerge', allowedFamilies: ['emerge', 'commit', 'signal']` , sin prewrite. Drag events (drag-start / drag-progress / drag-end / resize) intactos.
- Provider: `DISMISS_CAUSES` map + `dismissWith(action, opts?)` traduce a `dom.apply(data-last-action)` + `runtime.trigger('close', { semantic })` . `triggerClose` privado. 4 callsites internos migrados a `dismissWith` (Content escape, Content keydown escape, Overlay click-outside, Close button).
- Sema cascade (`sema/components/drawer.ts`): selector `eventNamePrefix: 'close-'` → `eventName: 'close', eventFamily: 'emerge'` .
- Test (`drawer-provider.svelte.test.ts`): `triggerClose('close-dismiss', ...)` → `dismissWith('dismiss')` ; expect name='close'.
**Popover**:
- Morfo: igual refactor. 5 close-* → 1 polymorphic `close` .
- Provider: igual patrón con DISMISS_CAUSES + dismissWith. Internal callsites (5 lugares: scheduleHoverClose, trigger toggle click, trigger toggle keydown, escape, outside) migrados a `dismissWith` . Close button: usa el prop `action` traducido a dismissWith.
- Sema cascade (`sema/components/popover.ts`): mismo patrón — `eventName: 'close'` + `state: { attr: 'data-last-action', value: 'dismissed-outside' }` para la regla de dismiss-outside passive.
- Test (`popover-provider.svelte.test.ts`): no había refs a close-* directos. Ningún cambio necesario.
**Test fixtures migrados antes del refactor**:
- `compile.test.ts` : prewrite test usaba `drawerMorfo` → ahora usa `colorPickerMorfo` .
- `runtime.svelte.test.ts` : prewrite test usaba `drawerMorfo` → ahora usa `colorPickerMorfo` .
**Resultado**:
- 3 componentes overlay (Dialog / Drawer / Popover) usan el patrón polymorphic close de forma consistente.
- 5 picker components (color-picker / date-picker / date-range-picker / time-picker / time-range-picker) mantienen el shape per-event. Son la canonical reference para `prewrite` declarativo + sirven como fixtures de tests.
- API pública intacta — `dismissWith` mantiene signatura en los tres overlays.
- Eidos CSS no tocó (ya leía `data-last-action` ).
**Tests**: 680/680 pass en `src/uix/sema + morfo + soma + src/arts/adom/test` . `npm run check` : 1 error pre-existente.
**Pendientes a futuro** (picker family cubierto en hand-off 2026-05-27 #4 ):
- ~~Picker family refactor~~ — DONE
- Otros `signal-warn-*` no cubiertos (textarea / tags-input ya hechos; revisar caso por caso si emergen más).
## Session hand-off — 2026-05-27 #4 (Picker family polymorphic close)
Cuarta tanda — completa el rollout polymorphic close al picker family (5 componentes). Más decoupling de tests.
**Refactor de los 5 pickers**:
- `color-picker` : 4 close-* → 1 polymorphic `close`
- `date-picker` : 4 close-* → 1 polymorphic `close`
- `date-range-picker` : 4 close-* (incl. `close-range-commit` ) → 1 polymorphic `close`
- `time-picker` : 4 close-* → 1 polymorphic `close`
- `time-range-picker` : 4 close-* → 1 polymorphic `close`
Cada morfo: `family: 'emerge', verb: 'close', target: v.partRef('calendar'|'clock'|'content'), persistence: 'transient', allowedFamilies: ['emerge', 'commit', 'signal']` .
**Hallazgo importante**: los picker providers NO disparan los close events. Solo togglean `opts.open = false` . Los eventos estaban declarados pero **inertes** — su único consumidor era el schema validator y los compiler tests. El refactor es alineación doctrinal, no de comportamiento.
**Sema cascade**: solo `color-picker` tiene un sema pack y no referenciaba close-* (solo handle-*). Cero updates necesarios en cascades.
**Test fixtures decoupling**:
- Nuevo `src/uix/morfo/test-fixtures.ts` con `prewriteFixtureMorfo` sintético.
- `compile.test.ts` : migrado de `colorPickerMorfo` → `prewriteFixtureMorfo` .
- `runtime.svelte.test.ts` : igual migración.
- Beneficio: los tests validan el contrato del compiler/runtime sin depender del catálogo de componentes. Futuros refactors del catálogo no rompen estos tests.
**Estado final del rollout polymorphic** (3 sprints combinados):
| Componente | Polymorphic morfo | Provider cabledado |
|---|---|---|
| Dialog | ✓ | ✓ (`dismissWith` → `runtime.trigger` ) |
| Drawer | ✓ | ✓ |
| Popover | ✓ | ✓ |
| color-picker | ✓ | ✗ (toggle opts.open) |
| date-picker | ✓ | ✗ |
| date-range-picker | ✓ | ✗ |
| time-picker | ✓ | ✗ |
| time-range-picker | ✓ | ✗ |
Único morfo con shape pre-polymorphic restante: el fixture sintético `prewriteFixtureMorfo` — vivo sólo para tests.
**Tests**: 680/680 pass. `npm run check` : 1 error pre-existente.
**Pendiente a futuro**:
- Cabledar `runtime.trigger('close', { semantic })` en los providers picker cuando justifique disparar el evento (telemetría, sound on commit picker, etc.).
feat(eidos): TSC v2.2 (parts + composition) + universal theming coverage
Token Scope Contract universal — no más excepciones arquitectónicas.
Los 3 componentes que vivían fuera de TSC v2.1 (select, avatar,
toggle-group) ahora están dentro del contrato via dos extensiones nuevas.
TSC v2.2 extensiones (lib/config-types.ts + render-css.ts + config.ts):
- `parts: readonly string[]` en RecipeTokenMultiDeclaration — emite
selectores comma-separados (`[data-{c}-x], [data-{c}-y]`) para
componentes con data-color cascadeado per-part. Consumer: select.
- `composition: { foreignRecipe: { targetSelector, tokens } }` sibling
key — overrides cross-recipe scoped a la cascade del host. Consumer:
toggle-group modifica `--toggle-palette-*` en sus items.
Migraciones:
- select: 3 private `_accent-{track,border,text}` con parts: ['trigger',
'content'] + 7 cascades color:X each. Removed orphan `_accent-solid`
(CSS no consumía).
- avatar: 6 tokens via composite scopes `['variant:X', 'color:Y']` con
matrix helper inline. Badge usa parts: ['badge']. Reemplaza 24 bloques
CSS × 2 partes.
- toggle-group: composition block con 8 palette tokens × 4 colors.
Reemplaza 4 bloques CSS per-color.
Bug toggle-group post-composition (encontrado y arreglado):
Tras la composition migration, el cascade del toggle-group seguía roto
porque los tokens derivados (`--toggle-solid-on-bg`, `--toggle-outline-fg`,
etc.) viven en scope `[data-toggle]`. El `[data-toggle-group-item]` es
sibling (no descendant), así que `var(--toggle-solid-on-bg)` resolvía
undefined. Fix: inlined derivation expressions directamente en
`[data-toggle-group-item]` y sus variant cascades (solid/outline/ghost),
referenciando palette tokens en su propio scope local.
Validador + emisor + contract:
- `validateRecipeComposition` valida el shape `{ targetSelector, tokens }`
y rechaza composition entries con scope='root'.
- `stripCompositionKey` + `emitComposition` separan el pipeline.
- `appendRecipeContractTokens` skip-list para `composition` (no aparece
como fake `--{c}-composition` knob).
- `tokenKeys`/`tokenEntries` helpers en recipe-css-contract.test.ts
filtran composition en todos los iteradores.
Documentación:
- THEMING.md §18 reescrito como "Cobertura universal de TSC". §7
extendido con subsecciones "Multi-part scope" y "Cross-recipe
composition" + ejemplos completos. TOC actualizado.
- eidos/README.md tabla de referencia ampliada con TSC v2.2 + §18.
- CLAUDE.md gana hand-off "2026-05-27 #5" (TSC v2.2 + cobertura universal).
- CONTINUE.md reescrito al estado actual de la sesión.
Working tree también incluye sprint Words en paralelo (multiple authors):
slash menu, find/replace regex, code language picker, table audit,
toolbar family menu, code highlight engine.
Tests: 786/786 pass en src/uix/{eidos,morfo,soma,sema}. `npm run check`:
6 errores pre-existentes (lib/_demo, soma/components/internal,
web/routes/active) no relacionados.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
## Session hand-off — 2026-05-27 #5 (TSC v2.2 + cobertura universal de theming)
Cierra la migración universal del Token Scope Contract. El usuario rechazó el framing "excepciones arquitectónicas" para los 3 componentes que vivían fuera de TSC v2.1 (`select`, `avatar` , `toggle-group` ) — la respuesta fue extender TSC con dos features nuevas (`parts` + `composition` ) y migrar los 3.
**Extensiones TSC v2.2** (`src/uix/eidos/lib/config-types.ts` + `lib/render-css.ts` + `lib/config.ts` ):
- **Multi-part scope** — `RecipeTokenMultiDeclaration.parts?: readonly string[]` . Cuando un token tiene `parts: ['x', 'y']` el generador emite selectores comma-separados (`[data-{c}-x][...], [data-{c}-y][...]`) en lugar del default `[data-{c}][...]` . Cubre el caso del select donde `data-color` vive en Trigger + Content (Content portaliza fuera del árbol del Trigger). Único consumer hoy.
- **Cross-recipe composition** — nuevo sibling field `composition?: { foreignComponent: { targetSelector, tokens } }` . Permite que un recipe declare overrides de tokens de OTRO recipe scoped a su propia cascade, con un selector de descendant para alcanzar la part foránea. Genera `{host-scope} {targetSelector} { --{foreign}-{tokenName}: ... }` . Validator rechaza root-scoped composition (un override no-scoped pertenece al foreign recipe). Único consumer hoy: `toggle-group` modifica `--toggle-palette-*` en sus items.
Validador (`config.ts`) extendido con `validateRecipeComposition` . Generator (`render-css.ts`) gana `stripCompositionKey` + `emitComposition` . Contract builder (`contract.ts`) skip-list de la reserved key `composition` para que no aparezca como `--{c}-composition` knob en el contrato público. Test helpers (`tokenKeys`/`tokenEntries` en `recipe-css-contract.test.ts` ) filtran `composition` en todos los iteradores.
**Migraciones de los 3 componentes restantes**:
- `select` : 4 → 3 private `_accent-*` con `parts: ['trigger', 'content']` . (`_accent-solid` no se migró porque la CSS nunca lo consumía — era orphan; se removió de la recipe.)
- `avatar` : 6 tokens (`_bg`/`_fg`/`_border` + `_badge-bg` /`_badge-fg`/`_badge-border`) con declarations[] generadas por un helper inline `matrix()` que recorre los 8 colores × 3 variants. `_badge-*` usa `parts: ['badge']` para retargetear a `[data-avatar-badge]` . Reemplaza ~150 declarations CSS por las mismas declarations, generadas desde TS.
- `toggle-group` : bloque `composition: { toggle: { targetSelector: '[data-toggle-group-item]', tokens: { 'palette-*': {...} } } }` con 8 palette tokens × 4 colors. Reemplaza los 4 bloques CSS per-color.
**Bug post-migración del toggle-group (toggle-group color cascade)** — encontrado y arreglado:
La composition correctamente override `--toggle-palette-*` en `[data-toggle-group-item]` , pero la cascade se rompía aguas abajo. Después de la migración TSC v2 original de toggle, los tokens DERIVADOS (`--toggle-solid-on-bg`, `--toggle-outline-fg` , etc.) viven en scope `[data-toggle]` . El `[data-toggle-group-item]` es SIBLING (no descendant) de `[data-toggle]` , así que `var(--toggle-solid-on-bg)` resolvía a undefined en el item.
Fix (en `toggle-group.css` ): **inlined las derivation expressions** que leen palette directamente en `[data-toggle-group-item]` y sus variant cascades. Las expresiones reflejan las de `recipes/base.ts > toggle.{solid,outline,ghost}-*` . Duplicación documentada en el header. Alternativa estructural (hacer el item carrier de `[data-toggle]` + propagar `data-color` morfo/soma) no se aplicó — change too big.
**Documentación**:
- `THEMING.md` §18 reescrito como "Cobertura universal de TSC" (sin excepciones). §7 extendido con subsecciones "Multi-part scope" y "Cross-recipe composition" con ejemplos completos. TOC actualizado.
- `eidos/README.md` tabla de referencia ampliada con entradas para TSC v2.2 + §18.
**Tests**: 786/786 pass en `src/uix/{eidos,morfo,soma,sema}` . `npm run check` : los mismos 6 errores pre-existentes en `lib/_demo` /`soma/components/internal`/`web/routes/active` (no relacionados).
**Pendiente a futuro**:
- Si emergen patrones similares al toggle-group (otros wrappers compositivos como button-group, nav-menu), la composition TSC v2.2 los cubre — no requiere más extensiones.
- Los `inlined derivation expressions` en `toggle-group.css` son la única duplicación entre recipes/base.ts y CSS. Si Toggle's derivations cambian, hay que actualizar ambos.
feat(eidos): variants canon — EIDOS_VARIANTS + per-component lint
Variants son canon del eidos, NO del theme. Decisión arquitectónica
firmemente sostenida: el vocabulario de variants (solid/outline/ghost/
soft/surface/line/pills) está fijo a nivel del framework — paralelo
a las 8 sema families del libro. Theme = retintar lo perceptualmente
fijo; cambia QUÉ color es `affirm`, no QUÉ significa `outline`.
Cambios:
- lib/types.ts: nueva constante `EIDOS_VARIANTS` con los 5 archetypes
canónicos (control / selection / chip / marker / tabs). Los 5 union
types se derivan via `[number]` indexed access — valor y tipo no
pueden desincronizarse. Nueva `EIDOS_VARIANT_VALUES` Set flat con
todos los valores canónicos + utilidades cross-component (`plain`,
`subtle`).
- recipe-css-contract.test.ts: nuevo test "variant CSS selectors per
component match the declared type union". Por cada componente:
extrae el union type de `components/{c}/types.ts` (soporta literal
unions + archetype aliases; cae a advisory mode en Extract<> y
conditional types); compara con `[data-{c}][data-variant='X']`
selectores en `{c}.css`; reporta typos y unauthorized extensions
bidireccionalmente.
- THEMING.md §19: nueva sección "Variants son canon del eidos, NO
del theme" con argumentación (portabilidad, type safety, archetypes
perceptuales paralelos a sema families), tabla de las 3 capas de
la cebolla, referencia a `EIDOS_VARIANTS`, comparación con Radix
Themes 3.x / Mantine 7 / Chakra v3 / Ark / shadcn. TOC actualizado.
- eidos/README.md: tabla de referencia ampliada con §19.
- CLAUDE.md: hand-off "2026-05-27 #6 (variants canon)".
- CONTINUE.md: nota de la decisión arquitectónica.
Variants component-specific permitidos (Banner inline/overlay/
persistent, Spinner bars/dots/ring, Button 'plain'): viven en cada
`components/{c}/types.ts` y el lint los valida contra la CSS del
componente.
Tests: 101/101 pass en `src/uix/eidos`. `npm run check`: los mismos 6
errores pre-existentes (lib/_demo, soma/components/internal, web/
routes/active) — no relacionados.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 months ago
## Session hand-off — 2026-05-27 #6 (variants canon — `EIDOS_VARIANTS` + lint)
Pregunta arquitectónica del usuario: "si activeUIX quiere ser referencia como framework, ¿qué es lo lógicamente coherente respecto a la extensibilidad de variants?". Respuesta firme: **variants son canon del eidos, NO del theme** — paralelo a las 8 sema families del libro.
**Cambios**:
- `src/uix/eidos/lib/types.ts` : nueva constante `EIDOS_VARIANTS` (5 archetypes: `control` /`selection`/`chip`/`marker`/`tabs`) como single source of truth. Los 5 union types se derivan via `[number]` indexed access — valor y tipo no pueden desincronizarse. Nueva constante `EIDOS_VARIANT_VALUES` (Set flat de todos los valores canónicos + utilidades cross-component como `'plain'` y `'subtle'` ).
- `src/uix/eidos/recipe-css-contract.test.ts` : nuevo test "variant CSS selectors per component match the declared type union". Por cada componente: extrae el union type de `components/{c}/types.ts` via regex (literal-union + archetype-alias patterns soportados, Extract< >/conditional types caen a advisory mode); compara con los `[data-{c}][data-variant='X']` selectores en `{c}.css` ; reporta typos y unauthorized extensions bidireccionalmente. 101/101 tests pasan.
- `src/uix/eidos/THEMING.md` §19: nueva sección "Variants son canon del eidos, NO del theme" con argumentación (portabilidad, type safety, archetypes perceptuales), tabla de las 3 capas de la cebolla (sema → variants → palette), referencia a `EIDOS_VARIANTS` , comparación con Radix Themes/Mantine/Chakra v3/Ark UI/shadcn. TOC actualizado.
- `src/uix/eidos/README.md` : tabla de referencia ampliada con §19.
**Doctrina sostenida**: Theme = retintar lo perceptualmente fijo. Cambia QUÉ color es `affirm` , no QUÉ significa `outline` . Si una app necesita un look brandeado, hace override de tokens en `EidosConfig.recipes` o crea un wrapper composicional — NO inventa un nuevo variant.
**Variants component-specific permitidos** (Banner `inline` /`overlay`/`persistent`, Spinner `bars` /`dots`/`ring`, Button `'plain'` ): viven en cada `components/{c}/types.ts` y el lint los valida contra la CSS del componente.
**Tests**: 101/101 pass en `src/uix/eidos` . `npm run check` : los mismos 6 errores pre-existentes (lib/_demo, soma/components/internal, web/routes/active).
refactor(toggle-group): item is structurally a Toggle (zero derivation duplication)
Closes the deuda left explicit in hand-off 2026-05-27 #5: the inlined
derivation expressions in toggle-group.css duplicated Toggle's recipe
because [data-toggle-group-item] wasn't a descendant of [data-toggle].
Resolution is structural, not a drift test:
- morfo: each item declares { attr: 'data-toggle', value: v.literal(''),
severity: 'required' }. Captures structural identity — an item IS a
toggle in every observable sense (same press, same variant/color/size,
same on/off machine).
- eidos: new context.ts propagates the root's variant + size via
reactive getters; the item wrapper writes them as data-attrs on its
button. Combined with data-toggle, the item is DOM-equivalent to a
standalone <Toggle>.
- eidos css: ~150 lines deleted (base derived tokens, variant cascades,
size cascade, focus/disabled/icon-only duplicates). Toggle's recipe
now paints the item end-to-end. CSS keeps only the grouping concerns:
flex, orientation, attached, block, focus z-index, group disabled.
- composition (TSC v2.2) stays — palette overrides land on the item
under [data-toggle-group][data-color='X'] [data-toggle-group-item],
which Toggle's --toggle-palette-* chain reads at item scope.
Verification:
- DOM probe (12 combinations: 4 colors × 3 variants × 2 states) on
/uix/components/toggle-group. Computed values match bit-a-bit with
baseline pre-refactor (e.g. affirm/solid on = rgb(18,165,148),
risk/outline on = srgb(0.2,0.118,0.043), threat/ghost on =
rgb(25,17,17)).
- vitest src/uix/{morfo,eidos}: 163/163 pass.
- vitest src/uix/soma/components/toggle-group: 4/4 pass.
- npm run check: 12 errors (all pre-existing in active Words sprint;
zero added by this migration).
Drive-by: the same npm-check pass surfaced 4 stale 'orientation' refs
in words-toolbar.svelte + words-toolbar-group.svelte from this session's
earlier toolbar refactor (orientation was removed from types but not
from these soma components). Removed; brings check from 16 → 12 errors.
CLAUDE.md hand-off 2026-05-28 documents the new doctrine: when a
wrapper visually reuses another, declare structural identity in the
wrapper's morfo. Don't duplicate the cascade, don't extend TSC for one
case.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 months ago
## Session hand-off — 2026-05-28 (toggle-group structural identity)
Cierra la deuda dejada explícitamente abierta en el hand-off 2026-05-27 #5 ("Los `inlined derivation expressions` en `toggle-group.css` son la única duplicación entre recipes/base.ts y CSS. Si Toggle's derivations cambian, hay que actualizar ambos."). Ahora son cero.
**Pregunta arquitectónica del usuario** tras verificar el fix EXT-FIX (color cascade): "¿qué es lo recomendado en referencia al ecosistema y su diseño y arquitectura?". Respuesta firme: **resolver la duplicación estructuralmente, no con un test de drift** . El item de toggle-group ES un toggle (mismo press, mismo variant/color/size, misma máquina on/off) — la doctrina "morfo declara DNA" pide declararlo.
**Cambios**:
- `src/uix/morfo/components/toggle-group.ts` : el part `Item` declara `{ attr: 'data-toggle', value: v.literal(''), severity: 'required' }` . Cada item proyecta `data-toggle=""` como atributo de presencia. Cero overhead, captura la identidad estructural.
- `src/uix/eidos/components/toggle-group/context.ts` (nuevo): contexto Svelte tipado (`ToggleGroupEidosCtx` con getters reactivos para `variant` y `size` ) — propaga las dos perillas eidos-only del root a cada item.
- `src/uix/eidos/components/toggle-group/toggle-group.svelte` : setea el contexto en el root. Getters mantienen reactividad cuando el prop cambia.
- `src/uix/eidos/components/toggle-group/toggle-group-item.svelte` : lee el contexto y escribe `data-variant={ctx?.variant}` + `data-size={ctx?.size}` en el button. Combinado con `data-toggle` del morfo, el elemento es DOM-equivalente a un `<Toggle>` standalone.
- `src/uix/eidos/components/toggle-group/toggle-group.css` : borradas ~150 líneas (todas las derivaciones base + variant cascade + size cascade + focus-visible / disabled / icon-only duplicados). El CSS conserva SOLO grouping concerns (flex layout, orientation, attached con first/last/border-radius, block, focus z-index, group-level disabled). El header comment se rescribe documentando la nueva división de responsabilidades.
- `src/uix/eidos/components/toggle-group/README.md` : sección "Recipe" + "Decisiones" actualizadas — la entrada "Structural identity" documenta el patrón.
**Por qué TSC v2.2 composition se queda en la mezcla**: la composition sigue siendo necesaria para overridear `--toggle-palette-*` en el item bajo `[data-toggle-group][data-color='X'] [data-toggle-group-item]` . El color NO se propaga via contexto porque la composition ya hace el trabajo a nivel CSS, sin overhead reactivo. Variant/size sí se propagan porque tienen muchos derivados (height, padding, gap, font, radius × 5 sizes; bg, fg, border, hover, on, on-hover × 3 variants) que solo Toggle's recipe ya emite — no había ningún beneficio en mantener cascadas paralelas.
**Verificación**: probe DOM en `/uix/components/toggle-group` capturando computed values en las 12 combinaciones (4 colores × 3 variants) × 2 estados (on/off) — match bit-a-bit con baseline pre-refactor. Ejemplos:
- `affirm/solid` on: `rgb(18,165,148)` = `#12a594` (palette-solid affirm)
- `risk/outline` on: `color(srgb 0.2 0.118 0.043)` ≈ `#331e0b` (color-mix outline on-bg)
- `threat/ghost` on: `rgb(25,17,17)` = `#191111` (palette-track threat)
**Tests**: 163/163 pass en `src/uix/morfo` + `src/uix/eidos` . 4/4 pass en `src/uix/soma/components/toggle-group` . `npm run check` : 16 errores pre-existentes (los mismos del sprint Words), CERO añadidos por esta migración.
**Coste real vs estimado**: el hand-off #5 estimó el cambio como "too big" — incorrecto. Total = 1 entrada en morfo + 1 archivo de contexto (~30 líneas) + 2 ediciones puntuales en wrappers (~5 líneas cada) + 1 rewrite de CSS reduciendo ~150 líneas a ~85. La parte engañosa era pensar que requería tocar Toggle's CSS — no lo hace.
**Doctrina reforzada**: cuando un wrapper componente reusa visualmente otro, la respuesta canónica NO es duplicar el cascade ni extender TSC con un tercer feature. Es declarar la identidad estructural en el morfo del wrapper. Patrón aplicable si emerge button-group, link-group, etc.
fix(words): silence canvas truly, drag for list/table, no overlay hovers + day-end docs
EV-G final pass + EOD documentation.
Words editor:
- Stop emitting `contact-focus` from soma. Removing the per-component
cascade rule earlier didn't fully silence the editor — the `contact`
family carries a BASE sound signature in SEMA_MAP (pitch 800, gain
0.25) that fires even without a cascade rule. The trigger call is
commented out (event no longer emitted; telemetry empty). Per spec:
"sigue apareciendo el puto sonido, el ring".
- Drag handle + inserter now cover lists AND tables. Selectors
expanded from `[data-words-node="block"][data-words-path]` to also
match `[data-words-node="list"]` and `[data-words-node="table"]`.
Top-level lists / tables get the grip + the "+" seam under them.
- Removed :hover from `[data-words-block-handle]` and
`[data-words-block-inserter-button]`. Gutter overlays are AMBIENT —
visual state via data-attrs only (`data-open`, `data-grabbed`,
`data-dragging`). Per spec: "quítale el hover al botón de añadir
bloque, si el handle no tiene este tampoco".
- Rail tokens hoisted to recipe: `words.rail-bg = #d4d4d4`,
`words.rail-border = #9a9a9a`. Fixed-tone (not theme-aware) — the
rail emulates the physical margin of a notebook; same look in
light/dark. Recipe-css-contract test was rejecting raw hex in
words.css.
Docs:
- CLAUDE.md hand-off 2026-05-28 #2 documenting the 6 EV-* Words
sprints + 5 architectural decisions with lasting effect (canvas
silent, fixed-tone tokens for physical metaphors, drag predicate
covers list/table, ambient overlays, insertParagraph empty-block
guard).
- continue.md (CONTINUE.md) rewritten for tomorrow's pickup:
TL;DR of the two halves (toggle-group structural + Words UX),
remaining bugs (drag handle outside rail on code blocks, heading
inline level change), and the heredados (POLISH-1b, F2.3-F2.6,
DRAGDROP-SOMA).
Verification: 467/467 morfo + sema + eidos + soma/words tests pass.
85/85 engine pass. `npm run check`: 0 errors.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 months ago
## Session hand-off — 2026-05-28 #2 (Words editor — 6 sprints UX)
Segunda mitad de la sesión (2026-05-28) dedicada a fixes del editor Words por feedback iterativo del usuario. Seis sprints EV-* + cleanup del check.
**Cleanup pre-sprint — `npm run check` 16 → 0**:
- 4 errores `orientation` drift en `soma/components/words-toolbar*` (deuda mía del sprint anterior — removí orientation del type pero no del soma component). Quitado el prop + create() call.
- 12 errores en el sprint Words activo (post-2026-05 F2/F3/COLOR): `onUploadImage` threading en soma `Words.Provider` , `'insert-image'` añadido a 2 Records `WordsToolbarButtonCommandName` , `leafItem` snippet hoisted FUERA de `<SomaWords.Provider>` (snippets dentro de un component element son props en Svelte 5; el snippet era helper local), 5 arrays inline en `words-drawer.svelte` extraídos a constantes typed `as const satisfies readonly { id: WordsCommandName | WordsMark; ... }[]` .
**EV-A — spam de eventos del canvas**:
- `isInsideWordsTool` extendido a los 5 overlays añadidos post-DRAWER: `data-words-drawer` , `data-words-block-handle` , `data-words-block-handle-menu` , `data-words-block-inserter` , `data-words-image-float-bar` . Antes, cualquier click sobre estos overlays se interpretaba como blur EXTERNO → fire `commit-save-content` + re-focus → fire `contact-focus` = 2 sonidos por interacción.
- `contact-focus` target movido de `content` a `provider` en morfo + sema cascade (doctrina: focus es evento de componente, no de body).
**EV-B — toolbar slim**:
- Presets demo (`minimal`/`formatting`/`full` + custom) reducidos a acciones GLOBALES: history (undo/redo) + insert + link + tools + find-replace. Text/block/list/align/table OUT porque el drawer ya los cubre por scope.
**EV-C — drag handle UX**:
- Borrado `e.dataTransfer.setDragImage(hoverBlockEl, 12, 12)` . El browser usa su snapshot por defecto (= el grip button) como ghost — el ghost viaja con el cursor mientras el bar en la gutter queda fijo como ancla visual. Nuevo `data-dragging` + CSS fade del ancla a 0.35 opacity.
**EV-D — inserter al borde inferior**:
- `seam.y` para seams entre bloques cambia de `(a.bottom + b.top) / 2` (midpoint) a `a.bottom` (borde inferior del bloque anterior). Half-open interval `[top, bottom)` para que el píxel exacto del bottom pertenezca al seam, no al bloque.
**EV-E — scroll interno del content**:
- Nuevo token `content-max-block-size-sm/md/lg` (50/60/70vh) en el recipe. `[data-words-content]` gana `max-block-size: var(--_words-content-max-block-size)` + `overflow-y: auto` . El min-block-size baseline queda como starting height para editores vacíos.
- block-handle / block-inserter / image-float-bar: scroll listeners migrados de `window.addEventListener('scroll')` a `document.addEventListener('scroll', { capture: true })` . Razón: scroll events NO burbujean — la versión anterior solo captaba scroll del root document; con la rail/handle/inserter ahora dentro de un content scrollable, había que capturar también scroll DENTRO del content para que las overlays se re-midieran.
**EV-F — paquete de 6 fixes en uno**:
1. Cascade sema de `contact-focus` REMOVIDA → canvas mudo en focus (EV-A fixaba solo el target; la cascade seguía sonando).
2. Rail bg → flat silver (`#d4d4d4`) + borde derecho `#9a9a9a` , sin dot pattern. Tokens `words.rail-bg / rail-border` en el recipe. **Fixed-tone, NOT theme-aware** — la intención es emular un margen físico de cuaderno, debe verse igual en dark/light theme.
3. Toolbar: `undo` + `redo` DIRECTOS (no popover); `insert-menu` eliminado. Resultado: 5 items.
4. Family-panel base 12.5 → 16rem · tools 17rem · link 20rem. Sin scroll horizontal.
5. Link popover sin scroll vertical (consecuencia del #4 ).
6. Engine `insertParagraph` con guarda explícita: paragraph vacío + Enter = no-op; heading vacío + Enter = demote a paragraph (canonical Notion UX).
**EV-G — último pass (parcial)**:
- `runtime.trigger('contact-focus')` comentado en soma. Causa real del sonido residual: la family `contact` en `SEMA_MAP` tiene BASE signature de sound (pitch 800, gain 0.25) que suena aunque no haya cascade per-component. Solución: no disparar el evento. Telemetry vacía para focus, aceptado.
- Drag handle + inserter ahora cubren `data-words-node="list"` y `data-words-node="table"` , no solo `"block"` . Los selectores en `findBlockElement` , `blockUnderCursorY` , `listBlockBoundaries` aceptan los tres tipos para top-level blocks. Listas y tablas tienen drag handle + inserter seam.
- `:hover` rules eliminadas en `[data-words-block-inserter-button]` y `[data-words-block-handle]` . Las overlays son AMBIENT — estado visual cambia solo en data attrs (`data-open`, `data-grabbed` , `data-dragging` ). No se iluminan en hover.
**Decisiones arquitectónicas con efecto duradero**:
- **Canvas perceptualmente silencioso** (Words): `contact-focus` no se emite. Si en el futuro un consumidor necesita el evento, descomentar el `runtime.trigger` en `words-provider.svelte.ts > onfocus` .
- **Tokens FIXED-TONE para concepto físico** (Words rail): `--words-rail-bg/border` son hex literal en el recipe, no `var(--color-*)` . Justificación: el concepto visual es "margen de papel" — debe verse igual en todos los themes.
- **Drag-handle predicate cubre 3 tipos de node**: `block` /`list`/`table`. No solo `block` . Cualquier nuevo top-level node type tiene que entrar en la lista.
- **Overlays ambient, no interactive buttons**: gutter overlays (block-handle, block-inserter button) no tienen `:hover` . Estado visual via data attrs solamente.
- **Engine guard sobre bloque vacío**: `insertParagraph` ya no duplica párrafos vacíos. Convierte heading→paragraph en vacío.
**Pendientes documentados en CONTINUE.md**:
- P1 — Drag handle aparece FUERA del rail sobre code blocks (no diagnosticado).
- P1 — Heading inline level change (h1↔h2↔h3) — la UI no permite cambiar nivel inline; el drawer Block panel lo tendría que ofrecer cuando `currentBlock === 'heading'` .
- POLISH-1b / POLISH-3 / WORDS-F2.3-F2.6 / WORDS-DRAGDROP-SOMA — heredados.
**Tests al cierre**: 467/467 pass en morfo + sema + eidos + soma/components/words. 85/85 engine pass. `npm run check` : **0 errors** .
## Session hand-off — 2026-05-09 (selector discipline + lint reframing)
- **Typed selector builder applied** in
`src/uix/sema/components/dialog.ts` . Every cascade rule now constructs
its selector via `semaSelector(dialogMorfo, 'content', matchers?)`
instead of hand-writing strings. The helper lives in
`src/uix/morfo/selectors.ts` and is exported from `$uix/morfo` .
- **Eidos-lint reframed** from "architectural drift mechanism" to
"opt-in safety net for plain CSS recipes". The architectural mechanism
is compile-time typing. The lint script + scripts continue to work
unchanged but are no longer the doctrinal source of safety.
- **Intent.deltas signature ownership documented** — cascade rules MUST
NOT override `pitch` / `gain` / `contour` on `sound` , because doing so
collapses the per-intent perceptual difference. Captured both inline
in the dialog cascade (NOTE comment on the intent block) and in the
"Override semantics — numbers" rule above.
- **Documentation updated**:
- `src/uix/morfo/README.md` — new "Typed selector builder —
`semaSelector` " section.
- `src/uix/eidos/README.md` — replaced "Linter" section with
"Defensa contra drift de selectores" framing the two-tier defense
(compile-time builder for TS/Svelte, opt-in lint for plain CSS).
- `src/uix/sema/README.md` — already documented the builder + the
cascade discipline + the SEMA_FAMILY_POLICY shape (from the prior
refactor).
**Verification at hand-off**: `npm run check` reports 0 errors, 2
pre-existing Svelte warnings unrelated to this work. `npm run test`
reports 1883/1883 tests green across 154 files (~22s).
docs + switch: align active docs to canon, migrate switch to eidos wrapper
Phase 4 (docs alignment with the canonical guide):
- active_architecture.md — Dialog example refactored to the new event
shape (target inside semantic, explicit verb + sequence). Verbs
table grouped by family with the post-canon vocabulary (select/
toggle moved to commit, edit removed from handle, new verbs added).
Section 10 (Estado actual) updated to 2026-05-08 with current
progress: doctrina cerrada, eidos en producción, SoundChannel
eager-init, switch migrated, etc. "Para profundizar" §14 points at
the canonical guide.
- morfo/README.md — Step 5.5 added covering the doctrinal event
shape with all fields (semantic.family, .verb, .target, .sequence,
.intent) and the two naming shapes ({verb}-{variant} and
{family}-{verb}).
- sema/README.md — verbs section restructured to Record-by-family
matching the runtime; documents the verbs that moved between
families per the canon. Naming shapes section updated with both
forms and validateEventName signature.
- CLAUDE.md — "Session hand-off" rewritten with the post-canon
state. Pointer at GUIA_IMPLEMENTACION_SEMAUIX.md as the canonical
source. Pending list refreshed: switch is the immediate next
component, persistence/a11ySemantic/polymorphism deferred until
real consumers appear.
Switch migration to the eidos wrapper pattern:
- morfo/components/switch.ts — adds events: [{ commit-toggle }] with
the doctrinal shape (verb=toggle, sequence=post, intent fromProp
binding to the 4 supported intents). New data-* (data-color with
the 6-token Toggle/Switch subset, data-readonly, data-invalid,
data-required) and corresponding aria-*. scope expanded to
['soma', 'sema'].
- soma/components/switch/types.ts — adds intent, color, readonly,
invalid, aria-labelledby props with full JSDoc. Subset constrained
per guide §3.1 (Toggle/Switch row).
- soma/components/switch/switch-provider.svelte.ts — runtime-direct,
Field integration via FieldProvider.get(), isDisabled/isReadonly/
isRequired/isInvalid OR-merge derivations, intent ↔ color
resolution (intent wins when evaluative), runtime.trigger(
'commit-toggle') in onclick.
- soma/components/switch/components/switch.svelte — wires the new
props through bindProps.
- eidos/components/switch/{switch.css, switch.svelte, types.ts,
index.ts, README.md} — full subdirectory pattern, mirroring
toggle. Recipe drops legacy success/warning/danger/info selectors;
declares the 6 doctrinal data-color values directly. Wrapper
auto-renders Switch.Thumb inside the track and exposes an optional
`thumb` snippet for in-thumb glyphs.
- eidos/components/switch.css (legacy flat) deleted; eidos/index.css
updated to import the subdirectory recipe.
- web/routes/switch/+page.svelte — interactive testbed with all soma
props as live controls + tabs (Live, Soma, Morfo, Sema, Eidos,
Notes). Mirrors toggle's structure.
npm run check holds at the 39-error baseline. Tests 217/217 green.
Pending:
- Migrate collapsible / dialog / drawer / popover / toast / avatar
to the eidos wrapper pattern.
- Persistence + holds-by-intent — defer until first signal.warn /
signal.alert consumer.
- a11ySemantic + polymorphic events — defer until concrete need.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
## Session hand-off — 2026-05-08 (post-canon alignment)
soma/morfo/active-uix: relocate runtime + rename SomaRuntime + sema opcional
Architectural correction. Morfo was importing Svelte runes, $adom, and
$uix/sema — all violations of "morfo is pure declarative DNA". The
runtime that interprets a CompiledMorfo lives where it executes: soma.
Move:
- src/uix/morfo/runtime.svelte.ts → src/uix/soma/runtime.svelte.ts
- src/uix/morfo/runtime.svelte.test.ts → src/uix/soma/runtime.svelte.test.ts
Rename (consistent with the move; "soma's runtime", per the doctrine
"morfo declares, soma executes"):
- class MorfoRuntime → SomaRuntime
- createMorfoRuntime() → createSomaRuntime()
- type MorfoRuntimeSources → SomaRuntimeSources
- error prefixes [morfo-runtime] → [soma-runtime]
Sema is now genuinely ornamental:
- ActiveUix.semantic returns EngineSemantic | undefined (no longer
throws when no engine is configured). Components in SSR / headless
tests / audio-disabled environments stay functional.
- SomaRuntime.trigger() skips the emit step AND the target-resolution
check when no engine is present — only requires a DOM target when
something will actually be emitted.
- Soma.semantic getter returns | undefined too (was non-optional).
Consumers updated:
- src/uix/active-uix/active-uix.svelte.ts — imports createSomaRuntime
from $soma; semantic getter returns | undefined
- src/uix/active-uix/types.ts — interface SomaRuntime, semantic | undefined
- 8 providers (toggle, switch, collapsible, dialog, drawer, popover,
toast, avatar) — type SomaRuntime, import path $soma
- src/uix/soma/index.ts — re-exports createSomaRuntime + types
- src/uix/morfo/index.ts — drops the runtime re-exports (morfo is pure)
- src/uix/sema/signal.ts — JSDoc reference updated
- src/uix/soma/core/soma.svelte.ts — semantic getter | undefined
Test added: SomaRuntime.trigger() succeeds without a semantic engine
(skips emit + target check, runs handler directly).
Docs aligned to the new shape:
- active_architecture.md — runtime locations, sema as ornamental
- soma/SOMA_ARCHITECTURE.md, soma/README.md — name + import paths
- morfo/README.md — file listing now flags morfo as PURE TS, points
at soma/runtime.svelte.ts for the interpreter
- sema/README.md — SomaRuntime references
- README.md — root architecture diagram
- CLAUDE.md — hand-off note
Tests 218/218 green. npm run check holds at the 39-error baseline.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
The codebase has been aligned to the canonical guide. Most recent
architectural move:
- **Runtime relocated + renamed** — what was `MorfoRuntime` in
`src/uix/morfo/runtime.svelte.ts` is now `SomaRuntime` in
`src/uix/soma/runtime.svelte.ts` . Reason: morfo must remain pure
declarative TypeScript (DNA); the runtime imports Svelte runes,
`$adom` , `$uix/sema` , and `$libs/reactive` — those are soma's
territory. Per the doctrine "morfo declares, soma executes" the
runtime now lives where it conceptually belongs. Active-uix's
`uix.runtime(morfo, sources)` factory stays unchanged; it imports
`createSomaRuntime` from `$soma` .
- **Sema is now genuinely ornamental** — `ActiveUix.semantic` returns
`EngineSemantic | undefined` (no longer throws). `SomaRuntime.trigger()`
skips the `emit` step and the target-resolution check when no engine
is present. Components stay functional in SSR / headless tests /
audio-disabled environments.
The earlier swept phases (still in effect):
docs + switch: align active docs to canon, migrate switch to eidos wrapper
Phase 4 (docs alignment with the canonical guide):
- active_architecture.md — Dialog example refactored to the new event
shape (target inside semantic, explicit verb + sequence). Verbs
table grouped by family with the post-canon vocabulary (select/
toggle moved to commit, edit removed from handle, new verbs added).
Section 10 (Estado actual) updated to 2026-05-08 with current
progress: doctrina cerrada, eidos en producción, SoundChannel
eager-init, switch migrated, etc. "Para profundizar" §14 points at
the canonical guide.
- morfo/README.md — Step 5.5 added covering the doctrinal event
shape with all fields (semantic.family, .verb, .target, .sequence,
.intent) and the two naming shapes ({verb}-{variant} and
{family}-{verb}).
- sema/README.md — verbs section restructured to Record-by-family
matching the runtime; documents the verbs that moved between
families per the canon. Naming shapes section updated with both
forms and validateEventName signature.
- CLAUDE.md — "Session hand-off" rewritten with the post-canon
state. Pointer at GUIA_IMPLEMENTACION_SEMAUIX.md as the canonical
source. Pending list refreshed: switch is the immediate next
component, persistence/a11ySemantic/polymorphism deferred until
real consumers appear.
Switch migration to the eidos wrapper pattern:
- morfo/components/switch.ts — adds events: [{ commit-toggle }] with
the doctrinal shape (verb=toggle, sequence=post, intent fromProp
binding to the 4 supported intents). New data-* (data-color with
the 6-token Toggle/Switch subset, data-readonly, data-invalid,
data-required) and corresponding aria-*. scope expanded to
['soma', 'sema'].
- soma/components/switch/types.ts — adds intent, color, readonly,
invalid, aria-labelledby props with full JSDoc. Subset constrained
per guide §3.1 (Toggle/Switch row).
- soma/components/switch/switch-provider.svelte.ts — runtime-direct,
Field integration via FieldProvider.get(), isDisabled/isReadonly/
isRequired/isInvalid OR-merge derivations, intent ↔ color
resolution (intent wins when evaluative), runtime.trigger(
'commit-toggle') in onclick.
- soma/components/switch/components/switch.svelte — wires the new
props through bindProps.
- eidos/components/switch/{switch.css, switch.svelte, types.ts,
index.ts, README.md} — full subdirectory pattern, mirroring
toggle. Recipe drops legacy success/warning/danger/info selectors;
declares the 6 doctrinal data-color values directly. Wrapper
auto-renders Switch.Thumb inside the track and exposes an optional
`thumb` snippet for in-thumb glyphs.
- eidos/components/switch.css (legacy flat) deleted; eidos/index.css
updated to import the subdirectory recipe.
- web/routes/switch/+page.svelte — interactive testbed with all soma
props as live controls + tabs (Live, Soma, Morfo, Sema, Eidos,
Notes). Mirrors toggle's structure.
npm run check holds at the 39-error baseline. Tests 217/217 green.
Pending:
- Migrate collapsible / dialog / drawer / popover / toast / avatar
to the eidos wrapper pattern.
- Persistence + holds-by-intent — defer until first signal.warn /
signal.alert consumer.
- a11ySemantic + polymorphic events — defer until concrete need.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
- **Sema verbs** (`src/uix/sema/verbs.ts`): restructured to
family-keyed `Record` . `select` /`toggle`/`acknowledge` moved to
`commit` ; `edit` removed from `handle` (now expressed as
`shift.enter-mode` ). New verbs added per the canon (tap, focus,
release, complete, restore, remind, route, step, syncing, etc.).
`validateEventName` recognises both `{verb}-{variant}` and
`{family}-{verb}` shapes.
- **Morfo event shape** (`src/uix/morfo/types.ts`): `target` moved
inside `semantic` ; added optional `verb` (advisory, validated against
`SEMA_VERBS[family]` ) and `sequence: 'pre' | 'coincident' | 'post'` .
All 22 events across toggle/toast/popover/drawer/dialog refactored
to the new shape.
- **Color tokens** (`src/uix/eidos/themes/base/{light,dark}.css`):
doctrinal 8 tokens — `primary, secondary, neutral, affirm, fulfill,
risk, threat, loss`. Renamed `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. Legacy
aliases in `_static.css` deleted (clean cut, no transition).
29 consumers (recipe CSS + tokens) migrated to doctrinal names.
Earlier in the session:
- **Toggle is the eidos pilot** (`src/uix/eidos/components/toggle/`):
recipe + Svelte wrapper + types + index + README. The pattern is
docs + switch: align active docs to canon, migrate switch to eidos wrapper
Phase 4 (docs alignment with the canonical guide):
- active_architecture.md — Dialog example refactored to the new event
shape (target inside semantic, explicit verb + sequence). Verbs
table grouped by family with the post-canon vocabulary (select/
toggle moved to commit, edit removed from handle, new verbs added).
Section 10 (Estado actual) updated to 2026-05-08 with current
progress: doctrina cerrada, eidos en producción, SoundChannel
eager-init, switch migrated, etc. "Para profundizar" §14 points at
the canonical guide.
- morfo/README.md — Step 5.5 added covering the doctrinal event
shape with all fields (semantic.family, .verb, .target, .sequence,
.intent) and the two naming shapes ({verb}-{variant} and
{family}-{verb}).
- sema/README.md — verbs section restructured to Record-by-family
matching the runtime; documents the verbs that moved between
families per the canon. Naming shapes section updated with both
forms and validateEventName signature.
- CLAUDE.md — "Session hand-off" rewritten with the post-canon
state. Pointer at GUIA_IMPLEMENTACION_SEMAUIX.md as the canonical
source. Pending list refreshed: switch is the immediate next
component, persistence/a11ySemantic/polymorphism deferred until
real consumers appear.
Switch migration to the eidos wrapper pattern:
- morfo/components/switch.ts — adds events: [{ commit-toggle }] with
the doctrinal shape (verb=toggle, sequence=post, intent fromProp
binding to the 4 supported intents). New data-* (data-color with
the 6-token Toggle/Switch subset, data-readonly, data-invalid,
data-required) and corresponding aria-*. scope expanded to
['soma', 'sema'].
- soma/components/switch/types.ts — adds intent, color, readonly,
invalid, aria-labelledby props with full JSDoc. Subset constrained
per guide §3.1 (Toggle/Switch row).
- soma/components/switch/switch-provider.svelte.ts — runtime-direct,
Field integration via FieldProvider.get(), isDisabled/isReadonly/
isRequired/isInvalid OR-merge derivations, intent ↔ color
resolution (intent wins when evaluative), runtime.trigger(
'commit-toggle') in onclick.
- soma/components/switch/components/switch.svelte — wires the new
props through bindProps.
- eidos/components/switch/{switch.css, switch.svelte, types.ts,
index.ts, README.md} — full subdirectory pattern, mirroring
toggle. Recipe drops legacy success/warning/danger/info selectors;
declares the 6 doctrinal data-color values directly. Wrapper
auto-renders Switch.Thumb inside the track and exposes an optional
`thumb` snippet for in-thumb glyphs.
- eidos/components/switch.css (legacy flat) deleted; eidos/index.css
updated to import the subdirectory recipe.
- web/routes/switch/+page.svelte — interactive testbed with all soma
props as live controls + tabs (Live, Soma, Morfo, Sema, Eidos,
Notes). Mirrors toggle's structure.
npm run check holds at the 39-error baseline. Tests 217/217 green.
Pending:
- Migrate collapsible / dialog / drawer / popover / toast / avatar
to the eidos wrapper pattern.
- Persistence + holds-by-intent — defer until first signal.warn /
signal.alert consumer.
- a11ySemantic + polymorphic events — defer until concrete need.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
documented in `src/uix/eidos/components/README.md` .
- **Eidos has a shared lib** at `src/uix/eidos/lib/types.ts` . First
type is `Size` (`'xxs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | 'full'`).
Components narrow with `Extract<Size, 'sm' | 'md' | 'lg'>` per the
per-component-subset doctrine.
- **No `Eidos` prefix on types**. The path
`$uix/eidos/components/{x}` already conveys layer. Public types are
`ToggleProps` , `ToggleVariant` , `ToggleSize` .
- **API doctrine**: soma stays compound (`Toggle.Provider`); eidos
exports both `default` and `Provider` for single-part components so
`<Toggle>` works for the ergonomic case while `<Toggle.Provider>`
stays available.
- **SoundChannel eager-init landed** in `src/uix/sema/chans/sound.ts`
to fix the autoplay race: the AudioContext is created + resumed
synchronously on the first user gesture (capture-phase listener on
`document` ).
- **Demo page (`web/routes/toggle/+page.svelte`)** has the live
preview rendered ALWAYS above the tablist (so Sema-tab Play buttons
can fire on the real toggle) and the motion preview amplifies scale
× 8 visually only — doctrinal values stay in the `<dl>` .
collapsible: migrate to eidos wrapper pattern (third pilot)
Third component migrated to the eidos wrapper subdirectory pattern,
following the new "check air baseline first" discipline.
Air baseline recovered from commit 0a391408^:
- air/components/collapsible: 3 wrappers (Provider/Trigger/Content)
with `class` passthrough, `bind:open`, `onOpenChange`, manual
`air.interaction.play('expansion', enter|exit)` perceptual emit.
- No size, intent, color, or chevron slot.
Migration decisions (presented BEFORE coding per scope-approval rule):
- Two doctrinal events (`expand` + `collapse`, both emerge family,
sequence='pre', no intent — emerge is transitional). Replaces air's
manual `air.interaction.play` with `runtime.trigger('expand'|
'collapse')` which atravieses visual + sound + vibra channels.
- No intent/color/size — air didn't have them and disclosure is
non-evaluative per guide §3.1.
- Multi-part API: Provider + Trigger + Content (no flat default per
doctrine §10).
Files:
- src/uix/morfo/components/collapsible.ts: scope expanded to ['soma',
'sema'], events array added with two emerge events.
- src/uix/soma/components/collapsible/collapsible-provider.svelte.ts:
runtime.events handlers `expand`/`collapse` mutate state; toggle()
fires runtime.trigger(next ? 'expand' : 'collapse').
- src/uix/eidos/components/collapsible/{collapsible.css,
collapsible-provider.svelte, collapsible-trigger.svelte,
collapsible-content.svelte, types.ts, index.ts, README.md}.
- src/uix/eidos/components/collapsible.css (legacy flat) deleted.
- src/uix/eidos/index.css: import path updated to subdirectory.
- web/routes/collapsible/+page.svelte: full interactive testbed with
tabs (Live, Soma, Morfo, Sema, Eidos, Notes) mirroring switch's
structure. Sema tab shows per-channel signature cards for both
expand and collapse events.
Disciplina formalizada en CLAUDE.md hand-off + memory entry: "Check
air baseline first" before any future eidos migration. Switch shipped
without this check and lost ResponsiveProp<Size> (regression). Don't
repeat with collapsible/dialog/drawer/popover/toast/avatar.
npm run check holds at the 39-error baseline. Tests 218/218 green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
**Mandatory checklist before any eidos component migration**:
1. Recover the air baseline from git:
```
git ls-tree -r 0a391408^ --name-only | Select-String "air.*{name}"
git show 0a391408^:src/uix/air/components/{name}/types.ts
git show 0a391408^:src/uix/air/components/{name}/{name}.svelte
```
2. Inventory air's props, slots, effects, perceptual emits.
3. Build a comparison table: feature × (air had it | canon allows it |
eidos exposes it). Flag each gap as `regression` , `enhanced` ,
`dropped-by-canon` , or `nuevo` .
4. Present the table BEFORE coding. Get explicit per-gap decision.
5. Only then write the wrapper.
Switch was migrated WITHOUT this discipline and shipped a regression
(no `ResponsiveProp<Size>` for breakpoint-aware sizing). Don't repeat.
Next concrete steps:
collapsible: migrate to eidos wrapper pattern (third pilot)
Third component migrated to the eidos wrapper subdirectory pattern,
following the new "check air baseline first" discipline.
Air baseline recovered from commit 0a391408^:
- air/components/collapsible: 3 wrappers (Provider/Trigger/Content)
with `class` passthrough, `bind:open`, `onOpenChange`, manual
`air.interaction.play('expansion', enter|exit)` perceptual emit.
- No size, intent, color, or chevron slot.
Migration decisions (presented BEFORE coding per scope-approval rule):
- Two doctrinal events (`expand` + `collapse`, both emerge family,
sequence='pre', no intent — emerge is transitional). Replaces air's
manual `air.interaction.play` with `runtime.trigger('expand'|
'collapse')` which atravieses visual + sound + vibra channels.
- No intent/color/size — air didn't have them and disclosure is
non-evaluative per guide §3.1.
- Multi-part API: Provider + Trigger + Content (no flat default per
doctrine §10).
Files:
- src/uix/morfo/components/collapsible.ts: scope expanded to ['soma',
'sema'], events array added with two emerge events.
- src/uix/soma/components/collapsible/collapsible-provider.svelte.ts:
runtime.events handlers `expand`/`collapse` mutate state; toggle()
fires runtime.trigger(next ? 'expand' : 'collapse').
- src/uix/eidos/components/collapsible/{collapsible.css,
collapsible-provider.svelte, collapsible-trigger.svelte,
collapsible-content.svelte, types.ts, index.ts, README.md}.
- src/uix/eidos/components/collapsible.css (legacy flat) deleted.
- src/uix/eidos/index.css: import path updated to subdirectory.
- web/routes/collapsible/+page.svelte: full interactive testbed with
tabs (Live, Soma, Morfo, Sema, Eidos, Notes) mirroring switch's
structure. Sema tab shows per-channel signature cards for both
expand and collapse events.
Disciplina formalizada en CLAUDE.md hand-off + memory entry: "Check
air baseline first" before any future eidos migration. Switch shipped
without this check and lost ResponsiveProp<Size> (regression). Don't
repeat with collapsible/dialog/drawer/popover/toast/avatar.
npm run check holds at the 39-error baseline. Tests 218/218 green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
1. Migrate `collapsible → dialog → drawer → popover → toast → avatar`
to the eidos wrapper pattern. **For each: walk the air-baseline
checklist above first.** Toggle / switch are templates for the
subdirectory shape, but the per-component prop surface must come
from air's recovery, not from copying toggle's props.
docs + switch: align active docs to canon, migrate switch to eidos wrapper
Phase 4 (docs alignment with the canonical guide):
- active_architecture.md — Dialog example refactored to the new event
shape (target inside semantic, explicit verb + sequence). Verbs
table grouped by family with the post-canon vocabulary (select/
toggle moved to commit, edit removed from handle, new verbs added).
Section 10 (Estado actual) updated to 2026-05-08 with current
progress: doctrina cerrada, eidos en producción, SoundChannel
eager-init, switch migrated, etc. "Para profundizar" §14 points at
the canonical guide.
- morfo/README.md — Step 5.5 added covering the doctrinal event
shape with all fields (semantic.family, .verb, .target, .sequence,
.intent) and the two naming shapes ({verb}-{variant} and
{family}-{verb}).
- sema/README.md — verbs section restructured to Record-by-family
matching the runtime; documents the verbs that moved between
families per the canon. Naming shapes section updated with both
forms and validateEventName signature.
- CLAUDE.md — "Session hand-off" rewritten with the post-canon
state. Pointer at GUIA_IMPLEMENTACION_SEMAUIX.md as the canonical
source. Pending list refreshed: switch is the immediate next
component, persistence/a11ySemantic/polymorphism deferred until
real consumers appear.
Switch migration to the eidos wrapper pattern:
- morfo/components/switch.ts — adds events: [{ commit-toggle }] with
the doctrinal shape (verb=toggle, sequence=post, intent fromProp
binding to the 4 supported intents). New data-* (data-color with
the 6-token Toggle/Switch subset, data-readonly, data-invalid,
data-required) and corresponding aria-*. scope expanded to
['soma', 'sema'].
- soma/components/switch/types.ts — adds intent, color, readonly,
invalid, aria-labelledby props with full JSDoc. Subset constrained
per guide §3.1 (Toggle/Switch row).
- soma/components/switch/switch-provider.svelte.ts — runtime-direct,
Field integration via FieldProvider.get(), isDisabled/isReadonly/
isRequired/isInvalid OR-merge derivations, intent ↔ color
resolution (intent wins when evaluative), runtime.trigger(
'commit-toggle') in onclick.
- soma/components/switch/components/switch.svelte — wires the new
props through bindProps.
- eidos/components/switch/{switch.css, switch.svelte, types.ts,
index.ts, README.md} — full subdirectory pattern, mirroring
toggle. Recipe drops legacy success/warning/danger/info selectors;
declares the 6 doctrinal data-color values directly. Wrapper
auto-renders Switch.Thumb inside the track and exposes an optional
`thumb` snippet for in-thumb glyphs.
- eidos/components/switch.css (legacy flat) deleted; eidos/index.css
updated to import the subdirectory recipe.
- web/routes/switch/+page.svelte — interactive testbed with all soma
props as live controls + tabs (Live, Soma, Morfo, Sema, Eidos,
Notes). Mirrors toggle's structure.
npm run check holds at the 39-error baseline. Tests 217/217 green.
Pending:
- Migrate collapsible / dialog / drawer / popover / toast / avatar
to the eidos wrapper pattern.
- Persistence + holds-by-intent — defer until first signal.warn /
signal.alert consumer.
- a11ySemantic + polymorphic events — defer until concrete need.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
2. **Persistence + holds-by-intent** (guide §6) — defer until the
first concrete `signal.warn` / `signal.alert` consumer appears.
Today every signal is `transient` with a numeric hold. Need to add
`persistence: 'transient' | 'untilAction' | 'untilFix' | 'stateBound'`
to `SemanticSignal` + the holds-by-intent table per the canon.
3. **a11ySemantic per event** (guide §9) — defer until there's a
reduced-motion runtime helper + live-region helper to consume the
contract.
4. **Polymorphic events** (guide §5.3, `allowedFamilies` +
`defaultSemantic` ) — defer; no current component needs polymorphism.
5. The docs site's topbar prefs (sound mute toggle, theme switcher)
are wired up but the sound mute does NOT yet drive
`SoundChannel.masterGain` . Wiring belongs on layout.svelte's `$effect` .
Baseline `npm run check` shows 39 pre-existing errors in test files
docs + switch: align active docs to canon, migrate switch to eidos wrapper
Phase 4 (docs alignment with the canonical guide):
- active_architecture.md — Dialog example refactored to the new event
shape (target inside semantic, explicit verb + sequence). Verbs
table grouped by family with the post-canon vocabulary (select/
toggle moved to commit, edit removed from handle, new verbs added).
Section 10 (Estado actual) updated to 2026-05-08 with current
progress: doctrina cerrada, eidos en producción, SoundChannel
eager-init, switch migrated, etc. "Para profundizar" §14 points at
the canonical guide.
- morfo/README.md — Step 5.5 added covering the doctrinal event
shape with all fields (semantic.family, .verb, .target, .sequence,
.intent) and the two naming shapes ({verb}-{variant} and
{family}-{verb}).
- sema/README.md — verbs section restructured to Record-by-family
matching the runtime; documents the verbs that moved between
families per the canon. Naming shapes section updated with both
forms and validateEventName signature.
- CLAUDE.md — "Session hand-off" rewritten with the post-canon
state. Pointer at GUIA_IMPLEMENTACION_SEMAUIX.md as the canonical
source. Pending list refreshed: switch is the immediate next
component, persistence/a11ySemantic/polymorphism deferred until
real consumers appear.
Switch migration to the eidos wrapper pattern:
- morfo/components/switch.ts — adds events: [{ commit-toggle }] with
the doctrinal shape (verb=toggle, sequence=post, intent fromProp
binding to the 4 supported intents). New data-* (data-color with
the 6-token Toggle/Switch subset, data-readonly, data-invalid,
data-required) and corresponding aria-*. scope expanded to
['soma', 'sema'].
- soma/components/switch/types.ts — adds intent, color, readonly,
invalid, aria-labelledby props with full JSDoc. Subset constrained
per guide §3.1 (Toggle/Switch row).
- soma/components/switch/switch-provider.svelte.ts — runtime-direct,
Field integration via FieldProvider.get(), isDisabled/isReadonly/
isRequired/isInvalid OR-merge derivations, intent ↔ color
resolution (intent wins when evaluative), runtime.trigger(
'commit-toggle') in onclick.
- soma/components/switch/components/switch.svelte — wires the new
props through bindProps.
- eidos/components/switch/{switch.css, switch.svelte, types.ts,
index.ts, README.md} — full subdirectory pattern, mirroring
toggle. Recipe drops legacy success/warning/danger/info selectors;
declares the 6 doctrinal data-color values directly. Wrapper
auto-renders Switch.Thumb inside the track and exposes an optional
`thumb` snippet for in-thumb glyphs.
- eidos/components/switch.css (legacy flat) deleted; eidos/index.css
updated to import the subdirectory recipe.
- web/routes/switch/+page.svelte — interactive testbed with all soma
props as live controls + tabs (Live, Soma, Morfo, Sema, Eidos,
Notes). Mirrors toggle's structure.
npm run check holds at the 39-error baseline. Tests 217/217 green.
Pending:
- Migrate collapsible / dialog / drawer / popover / toast / avatar
to the eidos wrapper pattern.
- Persistence + holds-by-intent — defer until first signal.warn /
signal.alert consumer.
- a11ySemantic + polymorphic events — defer until concrete need.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
unrelated to this work. Tests are 217/217 green across uix.
soma: dias date library, Calendar + RangeCalendar, Command fixes, doc updates
**Date library reorganisation** (no new third-party dependency)
- New `src/lib/util/dias/` with `_vendor/` (Adobe Apache 2.0 vendored code,
ATTRIBUTION.md preserved) and a public facade split into `types`,
`values`, `calendars`, `queries`, `operations`, `parse`, `format`,
`index`. Consumers import only from `$lib/util/dias`.
- All date-related `Intl` consolidated in `dias/format.ts` —
`DateFormatter`, cache, `resolveDateOrder`, `resolveHourCycle`,
placeholders, defaults.
- `ext/dates` now a thin reactive wrapper delegating to `dias`.
- Aligned App-layer `HourCycle` to canonical numeric form `12 | 24`
(matches `Intl.DateTimeFormat`'s `hour12`). Removed string form
`'12h' | '24h'` from `ext/app/types`, `ext/dates`,
`ext/presentation/locale-defaults`, and their tests.
- Repointed every consumer: `soma/external/dates`,
`terra/external/dates`, eight `routes/test/*` pages.
- Legacy `src/lib/util/dates/` left untouched by request.
**Tier 3 components**
- `soma/components/calendar/` — 14 parts, single + multiple selection,
`MonthSelect`/`YearSelect`, ISO/simple week numbers,
`isDateHoliday` matcher, `data-weekend` flag, navigation live-
region, RTL flip, full ARIA, 27-item checklist verified.
- `soma/components/range-calendar/` — 14 parts, range selection with
live hover preview (novel vs ark/bits/radix/react-aria), `minDays`
/ `maxDays` / `allowSingleDay`, third-click deselects only the
clicked endpoint.
- Test pages at `/test/soma/calendar` and `/test/soma/range-calendar`
with seven demos each. Links added to the soma index under a new
"Dates" section.
- READMEs with anatomy, parts, props, ARIA, keyboard, data-attrs, and
a competitive comparison table.
**Command fixes**
- Resolved O(N^2) reactive cascade: introduced
`visibleSet: $derived<Set<string>>` on the root provider;
per-item `isVisible` is now an O(1) `has()` lookup instead of
calling back into the provider, which was re-running all items'
derivations on every `itemsVersion` bump.
- Added `dir` prop with fallback to `soma.presentation.getDir()`;
horizontal arrows flip in RTL via `getDirectionalKeys`; root
receives `dir` attribute.
**Doc updates (session outcomes)**
- `CLAUDE.md`: replaced obsolete `@/glob/lib` date references with
`$lib/util/dias`; added canonical date-layer section; reinforced
`Provider` export rule and `data-{component}[-{part}]` naming
(never `data-soma-*`); clarified translation convention.
- `src/uix/soma/COMPONENT_GUIDE.md`: new checklist items 26
(component README required) and 27 (grep for data-attr
consistency); new Common Mistakes 11 (`data-soma-*` prefix), 12
(wrong date module), 13 (string `HourCycle`).
- `src/uix/soma/SOMA_ARCHITECTURE.md`: clarified data-attr naming
(canonical emitter is `createAttrs`; validator checks enum
values only, not names); new section covering date types and
formatting through `$soma/external/dates` → `$lib/util/dias`;
documented numeric `HourCycle`.
**Infrastructure**
- `PrimitiveHeaderAttributes` and `PrimitiveSelectAttributes` added
to `$soma/types`.
- `getLastFirstDayOfWeek`, `getNextLastDayOfWeek` re-exported from
`$soma/external/dates`.
- `calendar.*` and `range-calendar.*` translation blocks added to
`$soma/core/langs.ts`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
## 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 `<PickerShell>` ; 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).
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
---
soma: dias date library, Calendar + RangeCalendar, Command fixes, doc updates
**Date library reorganisation** (no new third-party dependency)
- New `src/lib/util/dias/` with `_vendor/` (Adobe Apache 2.0 vendored code,
ATTRIBUTION.md preserved) and a public facade split into `types`,
`values`, `calendars`, `queries`, `operations`, `parse`, `format`,
`index`. Consumers import only from `$lib/util/dias`.
- All date-related `Intl` consolidated in `dias/format.ts` —
`DateFormatter`, cache, `resolveDateOrder`, `resolveHourCycle`,
placeholders, defaults.
- `ext/dates` now a thin reactive wrapper delegating to `dias`.
- Aligned App-layer `HourCycle` to canonical numeric form `12 | 24`
(matches `Intl.DateTimeFormat`'s `hour12`). Removed string form
`'12h' | '24h'` from `ext/app/types`, `ext/dates`,
`ext/presentation/locale-defaults`, and their tests.
- Repointed every consumer: `soma/external/dates`,
`terra/external/dates`, eight `routes/test/*` pages.
- Legacy `src/lib/util/dates/` left untouched by request.
**Tier 3 components**
- `soma/components/calendar/` — 14 parts, single + multiple selection,
`MonthSelect`/`YearSelect`, ISO/simple week numbers,
`isDateHoliday` matcher, `data-weekend` flag, navigation live-
region, RTL flip, full ARIA, 27-item checklist verified.
- `soma/components/range-calendar/` — 14 parts, range selection with
live hover preview (novel vs ark/bits/radix/react-aria), `minDays`
/ `maxDays` / `allowSingleDay`, third-click deselects only the
clicked endpoint.
- Test pages at `/test/soma/calendar` and `/test/soma/range-calendar`
with seven demos each. Links added to the soma index under a new
"Dates" section.
- READMEs with anatomy, parts, props, ARIA, keyboard, data-attrs, and
a competitive comparison table.
**Command fixes**
- Resolved O(N^2) reactive cascade: introduced
`visibleSet: $derived<Set<string>>` on the root provider;
per-item `isVisible` is now an O(1) `has()` lookup instead of
calling back into the provider, which was re-running all items'
derivations on every `itemsVersion` bump.
- Added `dir` prop with fallback to `soma.presentation.getDir()`;
horizontal arrows flip in RTL via `getDirectionalKeys`; root
receives `dir` attribute.
**Doc updates (session outcomes)**
- `CLAUDE.md`: replaced obsolete `@/glob/lib` date references with
`$lib/util/dias`; added canonical date-layer section; reinforced
`Provider` export rule and `data-{component}[-{part}]` naming
(never `data-soma-*`); clarified translation convention.
- `src/uix/soma/COMPONENT_GUIDE.md`: new checklist items 26
(component README required) and 27 (grep for data-attr
consistency); new Common Mistakes 11 (`data-soma-*` prefix), 12
(wrong date module), 13 (string `HourCycle`).
- `src/uix/soma/SOMA_ARCHITECTURE.md`: clarified data-attr naming
(canonical emitter is `createAttrs`; validator checks enum
values only, not names); new section covering date types and
formatting through `$soma/external/dates` → `$lib/util/dias`;
documented numeric `HourCycle`.
**Infrastructure**
- `PrimitiveHeaderAttributes` and `PrimitiveSelectAttributes` added
to `$soma/types`.
- `getLastFirstDayOfWeek`, `getNextLastDayOfWeek` re-exported from
`$soma/external/dates`.
- `calendar.*` and `range-calendar.*` translation blocks added to
`$soma/core/langs.ts`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
# Behavioral Guidelines
soma: dias date library, Calendar + RangeCalendar, Command fixes, doc updates
**Date library reorganisation** (no new third-party dependency)
- New `src/lib/util/dias/` with `_vendor/` (Adobe Apache 2.0 vendored code,
ATTRIBUTION.md preserved) and a public facade split into `types`,
`values`, `calendars`, `queries`, `operations`, `parse`, `format`,
`index`. Consumers import only from `$lib/util/dias`.
- All date-related `Intl` consolidated in `dias/format.ts` —
`DateFormatter`, cache, `resolveDateOrder`, `resolveHourCycle`,
placeholders, defaults.
- `ext/dates` now a thin reactive wrapper delegating to `dias`.
- Aligned App-layer `HourCycle` to canonical numeric form `12 | 24`
(matches `Intl.DateTimeFormat`'s `hour12`). Removed string form
`'12h' | '24h'` from `ext/app/types`, `ext/dates`,
`ext/presentation/locale-defaults`, and their tests.
- Repointed every consumer: `soma/external/dates`,
`terra/external/dates`, eight `routes/test/*` pages.
- Legacy `src/lib/util/dates/` left untouched by request.
**Tier 3 components**
- `soma/components/calendar/` — 14 parts, single + multiple selection,
`MonthSelect`/`YearSelect`, ISO/simple week numbers,
`isDateHoliday` matcher, `data-weekend` flag, navigation live-
region, RTL flip, full ARIA, 27-item checklist verified.
- `soma/components/range-calendar/` — 14 parts, range selection with
live hover preview (novel vs ark/bits/radix/react-aria), `minDays`
/ `maxDays` / `allowSingleDay`, third-click deselects only the
clicked endpoint.
- Test pages at `/test/soma/calendar` and `/test/soma/range-calendar`
with seven demos each. Links added to the soma index under a new
"Dates" section.
- READMEs with anatomy, parts, props, ARIA, keyboard, data-attrs, and
a competitive comparison table.
**Command fixes**
- Resolved O(N^2) reactive cascade: introduced
`visibleSet: $derived<Set<string>>` on the root provider;
per-item `isVisible` is now an O(1) `has()` lookup instead of
calling back into the provider, which was re-running all items'
derivations on every `itemsVersion` bump.
- Added `dir` prop with fallback to `soma.presentation.getDir()`;
horizontal arrows flip in RTL via `getDirectionalKeys`; root
receives `dir` attribute.
**Doc updates (session outcomes)**
- `CLAUDE.md`: replaced obsolete `@/glob/lib` date references with
`$lib/util/dias`; added canonical date-layer section; reinforced
`Provider` export rule and `data-{component}[-{part}]` naming
(never `data-soma-*`); clarified translation convention.
- `src/uix/soma/COMPONENT_GUIDE.md`: new checklist items 26
(component README required) and 27 (grep for data-attr
consistency); new Common Mistakes 11 (`data-soma-*` prefix), 12
(wrong date module), 13 (string `HourCycle`).
- `src/uix/soma/SOMA_ARCHITECTURE.md`: clarified data-attr naming
(canonical emitter is `createAttrs`; validator checks enum
values only, not names); new section covering date types and
formatting through `$soma/external/dates` → `$lib/util/dias`;
documented numeric `HourCycle`.
**Infrastructure**
- `PrimitiveHeaderAttributes` and `PrimitiveSelectAttributes` added
to `$soma/types`.
- `getLastFirstDayOfWeek`, `getNextLastDayOfWeek` re-exported from
`$soma/external/dates`.
- `calendar.*` and `range-calendar.*` translation blocks added to
`$soma/core/langs.ts`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
These reduce common LLM coding mistakes. They bias toward caution over speed —
for trivial tasks, use judgment.
soma: dias date library, Calendar + RangeCalendar, Command fixes, doc updates
**Date library reorganisation** (no new third-party dependency)
- New `src/lib/util/dias/` with `_vendor/` (Adobe Apache 2.0 vendored code,
ATTRIBUTION.md preserved) and a public facade split into `types`,
`values`, `calendars`, `queries`, `operations`, `parse`, `format`,
`index`. Consumers import only from `$lib/util/dias`.
- All date-related `Intl` consolidated in `dias/format.ts` —
`DateFormatter`, cache, `resolveDateOrder`, `resolveHourCycle`,
placeholders, defaults.
- `ext/dates` now a thin reactive wrapper delegating to `dias`.
- Aligned App-layer `HourCycle` to canonical numeric form `12 | 24`
(matches `Intl.DateTimeFormat`'s `hour12`). Removed string form
`'12h' | '24h'` from `ext/app/types`, `ext/dates`,
`ext/presentation/locale-defaults`, and their tests.
- Repointed every consumer: `soma/external/dates`,
`terra/external/dates`, eight `routes/test/*` pages.
- Legacy `src/lib/util/dates/` left untouched by request.
**Tier 3 components**
- `soma/components/calendar/` — 14 parts, single + multiple selection,
`MonthSelect`/`YearSelect`, ISO/simple week numbers,
`isDateHoliday` matcher, `data-weekend` flag, navigation live-
region, RTL flip, full ARIA, 27-item checklist verified.
- `soma/components/range-calendar/` — 14 parts, range selection with
live hover preview (novel vs ark/bits/radix/react-aria), `minDays`
/ `maxDays` / `allowSingleDay`, third-click deselects only the
clicked endpoint.
- Test pages at `/test/soma/calendar` and `/test/soma/range-calendar`
with seven demos each. Links added to the soma index under a new
"Dates" section.
- READMEs with anatomy, parts, props, ARIA, keyboard, data-attrs, and
a competitive comparison table.
**Command fixes**
- Resolved O(N^2) reactive cascade: introduced
`visibleSet: $derived<Set<string>>` on the root provider;
per-item `isVisible` is now an O(1) `has()` lookup instead of
calling back into the provider, which was re-running all items'
derivations on every `itemsVersion` bump.
- Added `dir` prop with fallback to `soma.presentation.getDir()`;
horizontal arrows flip in RTL via `getDirectionalKeys`; root
receives `dir` attribute.
**Doc updates (session outcomes)**
- `CLAUDE.md`: replaced obsolete `@/glob/lib` date references with
`$lib/util/dias`; added canonical date-layer section; reinforced
`Provider` export rule and `data-{component}[-{part}]` naming
(never `data-soma-*`); clarified translation convention.
- `src/uix/soma/COMPONENT_GUIDE.md`: new checklist items 26
(component README required) and 27 (grep for data-attr
consistency); new Common Mistakes 11 (`data-soma-*` prefix), 12
(wrong date module), 13 (string `HourCycle`).
- `src/uix/soma/SOMA_ARCHITECTURE.md`: clarified data-attr naming
(canonical emitter is `createAttrs`; validator checks enum
values only, not names); new section covering date types and
formatting through `$soma/external/dates` → `$lib/util/dias`;
documented numeric `HourCycle`.
**Infrastructure**
- `PrimitiveHeaderAttributes` and `PrimitiveSelectAttributes` added
to `$soma/types`.
- `getLastFirstDayOfWeek`, `getNextLastDayOfWeek` re-exported from
`$soma/external/dates`.
- `calendar.*` and `range-calendar.*` translation blocks added to
`$soma/core/langs.ts`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
## 1. Think before coding
soma: dias date library, Calendar + RangeCalendar, Command fixes, doc updates
**Date library reorganisation** (no new third-party dependency)
- New `src/lib/util/dias/` with `_vendor/` (Adobe Apache 2.0 vendored code,
ATTRIBUTION.md preserved) and a public facade split into `types`,
`values`, `calendars`, `queries`, `operations`, `parse`, `format`,
`index`. Consumers import only from `$lib/util/dias`.
- All date-related `Intl` consolidated in `dias/format.ts` —
`DateFormatter`, cache, `resolveDateOrder`, `resolveHourCycle`,
placeholders, defaults.
- `ext/dates` now a thin reactive wrapper delegating to `dias`.
- Aligned App-layer `HourCycle` to canonical numeric form `12 | 24`
(matches `Intl.DateTimeFormat`'s `hour12`). Removed string form
`'12h' | '24h'` from `ext/app/types`, `ext/dates`,
`ext/presentation/locale-defaults`, and their tests.
- Repointed every consumer: `soma/external/dates`,
`terra/external/dates`, eight `routes/test/*` pages.
- Legacy `src/lib/util/dates/` left untouched by request.
**Tier 3 components**
- `soma/components/calendar/` — 14 parts, single + multiple selection,
`MonthSelect`/`YearSelect`, ISO/simple week numbers,
`isDateHoliday` matcher, `data-weekend` flag, navigation live-
region, RTL flip, full ARIA, 27-item checklist verified.
- `soma/components/range-calendar/` — 14 parts, range selection with
live hover preview (novel vs ark/bits/radix/react-aria), `minDays`
/ `maxDays` / `allowSingleDay`, third-click deselects only the
clicked endpoint.
- Test pages at `/test/soma/calendar` and `/test/soma/range-calendar`
with seven demos each. Links added to the soma index under a new
"Dates" section.
- READMEs with anatomy, parts, props, ARIA, keyboard, data-attrs, and
a competitive comparison table.
**Command fixes**
- Resolved O(N^2) reactive cascade: introduced
`visibleSet: $derived<Set<string>>` on the root provider;
per-item `isVisible` is now an O(1) `has()` lookup instead of
calling back into the provider, which was re-running all items'
derivations on every `itemsVersion` bump.
- Added `dir` prop with fallback to `soma.presentation.getDir()`;
horizontal arrows flip in RTL via `getDirectionalKeys`; root
receives `dir` attribute.
**Doc updates (session outcomes)**
- `CLAUDE.md`: replaced obsolete `@/glob/lib` date references with
`$lib/util/dias`; added canonical date-layer section; reinforced
`Provider` export rule and `data-{component}[-{part}]` naming
(never `data-soma-*`); clarified translation convention.
- `src/uix/soma/COMPONENT_GUIDE.md`: new checklist items 26
(component README required) and 27 (grep for data-attr
consistency); new Common Mistakes 11 (`data-soma-*` prefix), 12
(wrong date module), 13 (string `HourCycle`).
- `src/uix/soma/SOMA_ARCHITECTURE.md`: clarified data-attr naming
(canonical emitter is `createAttrs`; validator checks enum
values only, not names); new section covering date types and
formatting through `$soma/external/dates` → `$lib/util/dias`;
documented numeric `HourCycle`.
**Infrastructure**
- `PrimitiveHeaderAttributes` and `PrimitiveSelectAttributes` added
to `$soma/types`.
- `getLastFirstDayOfWeek`, `getNextLastDayOfWeek` re-exported from
`$soma/external/dates`.
- `calendar.*` and `range-calendar.*` translation blocks added to
`$soma/core/langs.ts`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
Don't assume. Don't hide confusion. Surface tradeoffs.
soma: dias date library, Calendar + RangeCalendar, Command fixes, doc updates
**Date library reorganisation** (no new third-party dependency)
- New `src/lib/util/dias/` with `_vendor/` (Adobe Apache 2.0 vendored code,
ATTRIBUTION.md preserved) and a public facade split into `types`,
`values`, `calendars`, `queries`, `operations`, `parse`, `format`,
`index`. Consumers import only from `$lib/util/dias`.
- All date-related `Intl` consolidated in `dias/format.ts` —
`DateFormatter`, cache, `resolveDateOrder`, `resolveHourCycle`,
placeholders, defaults.
- `ext/dates` now a thin reactive wrapper delegating to `dias`.
- Aligned App-layer `HourCycle` to canonical numeric form `12 | 24`
(matches `Intl.DateTimeFormat`'s `hour12`). Removed string form
`'12h' | '24h'` from `ext/app/types`, `ext/dates`,
`ext/presentation/locale-defaults`, and their tests.
- Repointed every consumer: `soma/external/dates`,
`terra/external/dates`, eight `routes/test/*` pages.
- Legacy `src/lib/util/dates/` left untouched by request.
**Tier 3 components**
- `soma/components/calendar/` — 14 parts, single + multiple selection,
`MonthSelect`/`YearSelect`, ISO/simple week numbers,
`isDateHoliday` matcher, `data-weekend` flag, navigation live-
region, RTL flip, full ARIA, 27-item checklist verified.
- `soma/components/range-calendar/` — 14 parts, range selection with
live hover preview (novel vs ark/bits/radix/react-aria), `minDays`
/ `maxDays` / `allowSingleDay`, third-click deselects only the
clicked endpoint.
- Test pages at `/test/soma/calendar` and `/test/soma/range-calendar`
with seven demos each. Links added to the soma index under a new
"Dates" section.
- READMEs with anatomy, parts, props, ARIA, keyboard, data-attrs, and
a competitive comparison table.
**Command fixes**
- Resolved O(N^2) reactive cascade: introduced
`visibleSet: $derived<Set<string>>` on the root provider;
per-item `isVisible` is now an O(1) `has()` lookup instead of
calling back into the provider, which was re-running all items'
derivations on every `itemsVersion` bump.
- Added `dir` prop with fallback to `soma.presentation.getDir()`;
horizontal arrows flip in RTL via `getDirectionalKeys`; root
receives `dir` attribute.
**Doc updates (session outcomes)**
- `CLAUDE.md`: replaced obsolete `@/glob/lib` date references with
`$lib/util/dias`; added canonical date-layer section; reinforced
`Provider` export rule and `data-{component}[-{part}]` naming
(never `data-soma-*`); clarified translation convention.
- `src/uix/soma/COMPONENT_GUIDE.md`: new checklist items 26
(component README required) and 27 (grep for data-attr
consistency); new Common Mistakes 11 (`data-soma-*` prefix), 12
(wrong date module), 13 (string `HourCycle`).
- `src/uix/soma/SOMA_ARCHITECTURE.md`: clarified data-attr naming
(canonical emitter is `createAttrs`; validator checks enum
values only, not names); new section covering date types and
formatting through `$soma/external/dates` → `$lib/util/dias`;
documented numeric `HourCycle`.
**Infrastructure**
- `PrimitiveHeaderAttributes` and `PrimitiveSelectAttributes` added
to `$soma/types`.
- `getLastFirstDayOfWeek`, `getNextLastDayOfWeek` re-exported from
`$soma/external/dates`.
- `calendar.*` and `range-calendar.*` translation blocks added to
`$soma/core/langs.ts`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
- State assumptions explicitly. If uncertain, ask.
- If multiple interpretations exist, present them — don't pick silently.
soma: dias date library, Calendar + RangeCalendar, Command fixes, doc updates
**Date library reorganisation** (no new third-party dependency)
- New `src/lib/util/dias/` with `_vendor/` (Adobe Apache 2.0 vendored code,
ATTRIBUTION.md preserved) and a public facade split into `types`,
`values`, `calendars`, `queries`, `operations`, `parse`, `format`,
`index`. Consumers import only from `$lib/util/dias`.
- All date-related `Intl` consolidated in `dias/format.ts` —
`DateFormatter`, cache, `resolveDateOrder`, `resolveHourCycle`,
placeholders, defaults.
- `ext/dates` now a thin reactive wrapper delegating to `dias`.
- Aligned App-layer `HourCycle` to canonical numeric form `12 | 24`
(matches `Intl.DateTimeFormat`'s `hour12`). Removed string form
`'12h' | '24h'` from `ext/app/types`, `ext/dates`,
`ext/presentation/locale-defaults`, and their tests.
- Repointed every consumer: `soma/external/dates`,
`terra/external/dates`, eight `routes/test/*` pages.
- Legacy `src/lib/util/dates/` left untouched by request.
**Tier 3 components**
- `soma/components/calendar/` — 14 parts, single + multiple selection,
`MonthSelect`/`YearSelect`, ISO/simple week numbers,
`isDateHoliday` matcher, `data-weekend` flag, navigation live-
region, RTL flip, full ARIA, 27-item checklist verified.
- `soma/components/range-calendar/` — 14 parts, range selection with
live hover preview (novel vs ark/bits/radix/react-aria), `minDays`
/ `maxDays` / `allowSingleDay`, third-click deselects only the
clicked endpoint.
- Test pages at `/test/soma/calendar` and `/test/soma/range-calendar`
with seven demos each. Links added to the soma index under a new
"Dates" section.
- READMEs with anatomy, parts, props, ARIA, keyboard, data-attrs, and
a competitive comparison table.
**Command fixes**
- Resolved O(N^2) reactive cascade: introduced
`visibleSet: $derived<Set<string>>` on the root provider;
per-item `isVisible` is now an O(1) `has()` lookup instead of
calling back into the provider, which was re-running all items'
derivations on every `itemsVersion` bump.
- Added `dir` prop with fallback to `soma.presentation.getDir()`;
horizontal arrows flip in RTL via `getDirectionalKeys`; root
receives `dir` attribute.
**Doc updates (session outcomes)**
- `CLAUDE.md`: replaced obsolete `@/glob/lib` date references with
`$lib/util/dias`; added canonical date-layer section; reinforced
`Provider` export rule and `data-{component}[-{part}]` naming
(never `data-soma-*`); clarified translation convention.
- `src/uix/soma/COMPONENT_GUIDE.md`: new checklist items 26
(component README required) and 27 (grep for data-attr
consistency); new Common Mistakes 11 (`data-soma-*` prefix), 12
(wrong date module), 13 (string `HourCycle`).
- `src/uix/soma/SOMA_ARCHITECTURE.md`: clarified data-attr naming
(canonical emitter is `createAttrs`; validator checks enum
values only, not names); new section covering date types and
formatting through `$soma/external/dates` → `$lib/util/dias`;
documented numeric `HourCycle`.
**Infrastructure**
- `PrimitiveHeaderAttributes` and `PrimitiveSelectAttributes` added
to `$soma/types`.
- `getLastFirstDayOfWeek`, `getNextLastDayOfWeek` re-exported from
`$soma/external/dates`.
- `calendar.*` and `range-calendar.*` translation blocks added to
`$soma/core/langs.ts`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
- If a simpler approach exists, say so. Push back when warranted.
- If something is unclear, stop. Name what's confusing. Ask.
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
## 2. Simplicity first
soma: dias date library, Calendar + RangeCalendar, Command fixes, doc updates
**Date library reorganisation** (no new third-party dependency)
- New `src/lib/util/dias/` with `_vendor/` (Adobe Apache 2.0 vendored code,
ATTRIBUTION.md preserved) and a public facade split into `types`,
`values`, `calendars`, `queries`, `operations`, `parse`, `format`,
`index`. Consumers import only from `$lib/util/dias`.
- All date-related `Intl` consolidated in `dias/format.ts` —
`DateFormatter`, cache, `resolveDateOrder`, `resolveHourCycle`,
placeholders, defaults.
- `ext/dates` now a thin reactive wrapper delegating to `dias`.
- Aligned App-layer `HourCycle` to canonical numeric form `12 | 24`
(matches `Intl.DateTimeFormat`'s `hour12`). Removed string form
`'12h' | '24h'` from `ext/app/types`, `ext/dates`,
`ext/presentation/locale-defaults`, and their tests.
- Repointed every consumer: `soma/external/dates`,
`terra/external/dates`, eight `routes/test/*` pages.
- Legacy `src/lib/util/dates/` left untouched by request.
**Tier 3 components**
- `soma/components/calendar/` — 14 parts, single + multiple selection,
`MonthSelect`/`YearSelect`, ISO/simple week numbers,
`isDateHoliday` matcher, `data-weekend` flag, navigation live-
region, RTL flip, full ARIA, 27-item checklist verified.
- `soma/components/range-calendar/` — 14 parts, range selection with
live hover preview (novel vs ark/bits/radix/react-aria), `minDays`
/ `maxDays` / `allowSingleDay`, third-click deselects only the
clicked endpoint.
- Test pages at `/test/soma/calendar` and `/test/soma/range-calendar`
with seven demos each. Links added to the soma index under a new
"Dates" section.
- READMEs with anatomy, parts, props, ARIA, keyboard, data-attrs, and
a competitive comparison table.
**Command fixes**
- Resolved O(N^2) reactive cascade: introduced
`visibleSet: $derived<Set<string>>` on the root provider;
per-item `isVisible` is now an O(1) `has()` lookup instead of
calling back into the provider, which was re-running all items'
derivations on every `itemsVersion` bump.
- Added `dir` prop with fallback to `soma.presentation.getDir()`;
horizontal arrows flip in RTL via `getDirectionalKeys`; root
receives `dir` attribute.
**Doc updates (session outcomes)**
- `CLAUDE.md`: replaced obsolete `@/glob/lib` date references with
`$lib/util/dias`; added canonical date-layer section; reinforced
`Provider` export rule and `data-{component}[-{part}]` naming
(never `data-soma-*`); clarified translation convention.
- `src/uix/soma/COMPONENT_GUIDE.md`: new checklist items 26
(component README required) and 27 (grep for data-attr
consistency); new Common Mistakes 11 (`data-soma-*` prefix), 12
(wrong date module), 13 (string `HourCycle`).
- `src/uix/soma/SOMA_ARCHITECTURE.md`: clarified data-attr naming
(canonical emitter is `createAttrs`; validator checks enum
values only, not names); new section covering date types and
formatting through `$soma/external/dates` → `$lib/util/dias`;
documented numeric `HourCycle`.
**Infrastructure**
- `PrimitiveHeaderAttributes` and `PrimitiveSelectAttributes` added
to `$soma/types`.
- `getLastFirstDayOfWeek`, `getNextLastDayOfWeek` re-exported from
`$soma/external/dates`.
- `calendar.*` and `range-calendar.*` translation blocks added to
`$soma/core/langs.ts`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
Minimum code that solves the problem. Nothing speculative.
soma: dias date library, Calendar + RangeCalendar, Command fixes, doc updates
**Date library reorganisation** (no new third-party dependency)
- New `src/lib/util/dias/` with `_vendor/` (Adobe Apache 2.0 vendored code,
ATTRIBUTION.md preserved) and a public facade split into `types`,
`values`, `calendars`, `queries`, `operations`, `parse`, `format`,
`index`. Consumers import only from `$lib/util/dias`.
- All date-related `Intl` consolidated in `dias/format.ts` —
`DateFormatter`, cache, `resolveDateOrder`, `resolveHourCycle`,
placeholders, defaults.
- `ext/dates` now a thin reactive wrapper delegating to `dias`.
- Aligned App-layer `HourCycle` to canonical numeric form `12 | 24`
(matches `Intl.DateTimeFormat`'s `hour12`). Removed string form
`'12h' | '24h'` from `ext/app/types`, `ext/dates`,
`ext/presentation/locale-defaults`, and their tests.
- Repointed every consumer: `soma/external/dates`,
`terra/external/dates`, eight `routes/test/*` pages.
- Legacy `src/lib/util/dates/` left untouched by request.
**Tier 3 components**
- `soma/components/calendar/` — 14 parts, single + multiple selection,
`MonthSelect`/`YearSelect`, ISO/simple week numbers,
`isDateHoliday` matcher, `data-weekend` flag, navigation live-
region, RTL flip, full ARIA, 27-item checklist verified.
- `soma/components/range-calendar/` — 14 parts, range selection with
live hover preview (novel vs ark/bits/radix/react-aria), `minDays`
/ `maxDays` / `allowSingleDay`, third-click deselects only the
clicked endpoint.
- Test pages at `/test/soma/calendar` and `/test/soma/range-calendar`
with seven demos each. Links added to the soma index under a new
"Dates" section.
- READMEs with anatomy, parts, props, ARIA, keyboard, data-attrs, and
a competitive comparison table.
**Command fixes**
- Resolved O(N^2) reactive cascade: introduced
`visibleSet: $derived<Set<string>>` on the root provider;
per-item `isVisible` is now an O(1) `has()` lookup instead of
calling back into the provider, which was re-running all items'
derivations on every `itemsVersion` bump.
- Added `dir` prop with fallback to `soma.presentation.getDir()`;
horizontal arrows flip in RTL via `getDirectionalKeys`; root
receives `dir` attribute.
**Doc updates (session outcomes)**
- `CLAUDE.md`: replaced obsolete `@/glob/lib` date references with
`$lib/util/dias`; added canonical date-layer section; reinforced
`Provider` export rule and `data-{component}[-{part}]` naming
(never `data-soma-*`); clarified translation convention.
- `src/uix/soma/COMPONENT_GUIDE.md`: new checklist items 26
(component README required) and 27 (grep for data-attr
consistency); new Common Mistakes 11 (`data-soma-*` prefix), 12
(wrong date module), 13 (string `HourCycle`).
- `src/uix/soma/SOMA_ARCHITECTURE.md`: clarified data-attr naming
(canonical emitter is `createAttrs`; validator checks enum
values only, not names); new section covering date types and
formatting through `$soma/external/dates` → `$lib/util/dias`;
documented numeric `HourCycle`.
**Infrastructure**
- `PrimitiveHeaderAttributes` and `PrimitiveSelectAttributes` added
to `$soma/types`.
- `getLastFirstDayOfWeek`, `getNextLastDayOfWeek` re-exported from
`$soma/external/dates`.
- `calendar.*` and `range-calendar.*` translation blocks added to
`$soma/core/langs.ts`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
- No features beyond what was asked.
- No abstractions for single-use code.
- No "flexibility" or "configurability" that wasn't requested.
- No error handling for impossible scenarios.
- If you write 200 lines and it could be 50, rewrite it.
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
## 3. Surgical changes
soma: dias date library, Calendar + RangeCalendar, Command fixes, doc updates
**Date library reorganisation** (no new third-party dependency)
- New `src/lib/util/dias/` with `_vendor/` (Adobe Apache 2.0 vendored code,
ATTRIBUTION.md preserved) and a public facade split into `types`,
`values`, `calendars`, `queries`, `operations`, `parse`, `format`,
`index`. Consumers import only from `$lib/util/dias`.
- All date-related `Intl` consolidated in `dias/format.ts` —
`DateFormatter`, cache, `resolveDateOrder`, `resolveHourCycle`,
placeholders, defaults.
- `ext/dates` now a thin reactive wrapper delegating to `dias`.
- Aligned App-layer `HourCycle` to canonical numeric form `12 | 24`
(matches `Intl.DateTimeFormat`'s `hour12`). Removed string form
`'12h' | '24h'` from `ext/app/types`, `ext/dates`,
`ext/presentation/locale-defaults`, and their tests.
- Repointed every consumer: `soma/external/dates`,
`terra/external/dates`, eight `routes/test/*` pages.
- Legacy `src/lib/util/dates/` left untouched by request.
**Tier 3 components**
- `soma/components/calendar/` — 14 parts, single + multiple selection,
`MonthSelect`/`YearSelect`, ISO/simple week numbers,
`isDateHoliday` matcher, `data-weekend` flag, navigation live-
region, RTL flip, full ARIA, 27-item checklist verified.
- `soma/components/range-calendar/` — 14 parts, range selection with
live hover preview (novel vs ark/bits/radix/react-aria), `minDays`
/ `maxDays` / `allowSingleDay`, third-click deselects only the
clicked endpoint.
- Test pages at `/test/soma/calendar` and `/test/soma/range-calendar`
with seven demos each. Links added to the soma index under a new
"Dates" section.
- READMEs with anatomy, parts, props, ARIA, keyboard, data-attrs, and
a competitive comparison table.
**Command fixes**
- Resolved O(N^2) reactive cascade: introduced
`visibleSet: $derived<Set<string>>` on the root provider;
per-item `isVisible` is now an O(1) `has()` lookup instead of
calling back into the provider, which was re-running all items'
derivations on every `itemsVersion` bump.
- Added `dir` prop with fallback to `soma.presentation.getDir()`;
horizontal arrows flip in RTL via `getDirectionalKeys`; root
receives `dir` attribute.
**Doc updates (session outcomes)**
- `CLAUDE.md`: replaced obsolete `@/glob/lib` date references with
`$lib/util/dias`; added canonical date-layer section; reinforced
`Provider` export rule and `data-{component}[-{part}]` naming
(never `data-soma-*`); clarified translation convention.
- `src/uix/soma/COMPONENT_GUIDE.md`: new checklist items 26
(component README required) and 27 (grep for data-attr
consistency); new Common Mistakes 11 (`data-soma-*` prefix), 12
(wrong date module), 13 (string `HourCycle`).
- `src/uix/soma/SOMA_ARCHITECTURE.md`: clarified data-attr naming
(canonical emitter is `createAttrs`; validator checks enum
values only, not names); new section covering date types and
formatting through `$soma/external/dates` → `$lib/util/dias`;
documented numeric `HourCycle`.
**Infrastructure**
- `PrimitiveHeaderAttributes` and `PrimitiveSelectAttributes` added
to `$soma/types`.
- `getLastFirstDayOfWeek`, `getNextLastDayOfWeek` re-exported from
`$soma/external/dates`.
- `calendar.*` and `range-calendar.*` translation blocks added to
`$soma/core/langs.ts`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
Touch only what you must. Clean up only your own mess.
soma: dias date library, Calendar + RangeCalendar, Command fixes, doc updates
**Date library reorganisation** (no new third-party dependency)
- New `src/lib/util/dias/` with `_vendor/` (Adobe Apache 2.0 vendored code,
ATTRIBUTION.md preserved) and a public facade split into `types`,
`values`, `calendars`, `queries`, `operations`, `parse`, `format`,
`index`. Consumers import only from `$lib/util/dias`.
- All date-related `Intl` consolidated in `dias/format.ts` —
`DateFormatter`, cache, `resolveDateOrder`, `resolveHourCycle`,
placeholders, defaults.
- `ext/dates` now a thin reactive wrapper delegating to `dias`.
- Aligned App-layer `HourCycle` to canonical numeric form `12 | 24`
(matches `Intl.DateTimeFormat`'s `hour12`). Removed string form
`'12h' | '24h'` from `ext/app/types`, `ext/dates`,
`ext/presentation/locale-defaults`, and their tests.
- Repointed every consumer: `soma/external/dates`,
`terra/external/dates`, eight `routes/test/*` pages.
- Legacy `src/lib/util/dates/` left untouched by request.
**Tier 3 components**
- `soma/components/calendar/` — 14 parts, single + multiple selection,
`MonthSelect`/`YearSelect`, ISO/simple week numbers,
`isDateHoliday` matcher, `data-weekend` flag, navigation live-
region, RTL flip, full ARIA, 27-item checklist verified.
- `soma/components/range-calendar/` — 14 parts, range selection with
live hover preview (novel vs ark/bits/radix/react-aria), `minDays`
/ `maxDays` / `allowSingleDay`, third-click deselects only the
clicked endpoint.
- Test pages at `/test/soma/calendar` and `/test/soma/range-calendar`
with seven demos each. Links added to the soma index under a new
"Dates" section.
- READMEs with anatomy, parts, props, ARIA, keyboard, data-attrs, and
a competitive comparison table.
**Command fixes**
- Resolved O(N^2) reactive cascade: introduced
`visibleSet: $derived<Set<string>>` on the root provider;
per-item `isVisible` is now an O(1) `has()` lookup instead of
calling back into the provider, which was re-running all items'
derivations on every `itemsVersion` bump.
- Added `dir` prop with fallback to `soma.presentation.getDir()`;
horizontal arrows flip in RTL via `getDirectionalKeys`; root
receives `dir` attribute.
**Doc updates (session outcomes)**
- `CLAUDE.md`: replaced obsolete `@/glob/lib` date references with
`$lib/util/dias`; added canonical date-layer section; reinforced
`Provider` export rule and `data-{component}[-{part}]` naming
(never `data-soma-*`); clarified translation convention.
- `src/uix/soma/COMPONENT_GUIDE.md`: new checklist items 26
(component README required) and 27 (grep for data-attr
consistency); new Common Mistakes 11 (`data-soma-*` prefix), 12
(wrong date module), 13 (string `HourCycle`).
- `src/uix/soma/SOMA_ARCHITECTURE.md`: clarified data-attr naming
(canonical emitter is `createAttrs`; validator checks enum
values only, not names); new section covering date types and
formatting through `$soma/external/dates` → `$lib/util/dias`;
documented numeric `HourCycle`.
**Infrastructure**
- `PrimitiveHeaderAttributes` and `PrimitiveSelectAttributes` added
to `$soma/types`.
- `getLastFirstDayOfWeek`, `getNextLastDayOfWeek` re-exported from
`$soma/external/dates`.
- `calendar.*` and `range-calendar.*` translation blocks added to
`$soma/core/langs.ts`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
- Don't "improve" adjacent code, comments, or formatting.
- Don't refactor things that aren't broken.
- Match existing style, even if you'd do it differently.
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
- If you notice unrelated dead code, mention it — don't delete it.
soma: dias date library, Calendar + RangeCalendar, Command fixes, doc updates
**Date library reorganisation** (no new third-party dependency)
- New `src/lib/util/dias/` with `_vendor/` (Adobe Apache 2.0 vendored code,
ATTRIBUTION.md preserved) and a public facade split into `types`,
`values`, `calendars`, `queries`, `operations`, `parse`, `format`,
`index`. Consumers import only from `$lib/util/dias`.
- All date-related `Intl` consolidated in `dias/format.ts` —
`DateFormatter`, cache, `resolveDateOrder`, `resolveHourCycle`,
placeholders, defaults.
- `ext/dates` now a thin reactive wrapper delegating to `dias`.
- Aligned App-layer `HourCycle` to canonical numeric form `12 | 24`
(matches `Intl.DateTimeFormat`'s `hour12`). Removed string form
`'12h' | '24h'` from `ext/app/types`, `ext/dates`,
`ext/presentation/locale-defaults`, and their tests.
- Repointed every consumer: `soma/external/dates`,
`terra/external/dates`, eight `routes/test/*` pages.
- Legacy `src/lib/util/dates/` left untouched by request.
**Tier 3 components**
- `soma/components/calendar/` — 14 parts, single + multiple selection,
`MonthSelect`/`YearSelect`, ISO/simple week numbers,
`isDateHoliday` matcher, `data-weekend` flag, navigation live-
region, RTL flip, full ARIA, 27-item checklist verified.
- `soma/components/range-calendar/` — 14 parts, range selection with
live hover preview (novel vs ark/bits/radix/react-aria), `minDays`
/ `maxDays` / `allowSingleDay`, third-click deselects only the
clicked endpoint.
- Test pages at `/test/soma/calendar` and `/test/soma/range-calendar`
with seven demos each. Links added to the soma index under a new
"Dates" section.
- READMEs with anatomy, parts, props, ARIA, keyboard, data-attrs, and
a competitive comparison table.
**Command fixes**
- Resolved O(N^2) reactive cascade: introduced
`visibleSet: $derived<Set<string>>` on the root provider;
per-item `isVisible` is now an O(1) `has()` lookup instead of
calling back into the provider, which was re-running all items'
derivations on every `itemsVersion` bump.
- Added `dir` prop with fallback to `soma.presentation.getDir()`;
horizontal arrows flip in RTL via `getDirectionalKeys`; root
receives `dir` attribute.
**Doc updates (session outcomes)**
- `CLAUDE.md`: replaced obsolete `@/glob/lib` date references with
`$lib/util/dias`; added canonical date-layer section; reinforced
`Provider` export rule and `data-{component}[-{part}]` naming
(never `data-soma-*`); clarified translation convention.
- `src/uix/soma/COMPONENT_GUIDE.md`: new checklist items 26
(component README required) and 27 (grep for data-attr
consistency); new Common Mistakes 11 (`data-soma-*` prefix), 12
(wrong date module), 13 (string `HourCycle`).
- `src/uix/soma/SOMA_ARCHITECTURE.md`: clarified data-attr naming
(canonical emitter is `createAttrs`; validator checks enum
values only, not names); new section covering date types and
formatting through `$soma/external/dates` → `$lib/util/dias`;
documented numeric `HourCycle`.
**Infrastructure**
- `PrimitiveHeaderAttributes` and `PrimitiveSelectAttributes` added
to `$soma/types`.
- `getLastFirstDayOfWeek`, `getNextLastDayOfWeek` re-exported from
`$soma/external/dates`.
- `calendar.*` and `range-calendar.*` translation blocks added to
`$soma/core/langs.ts`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
When your changes create orphans, remove the imports / variables / functions
your changes made unused. Don't remove pre-existing dead code unless asked.
soma: dias date library, Calendar + RangeCalendar, Command fixes, doc updates
**Date library reorganisation** (no new third-party dependency)
- New `src/lib/util/dias/` with `_vendor/` (Adobe Apache 2.0 vendored code,
ATTRIBUTION.md preserved) and a public facade split into `types`,
`values`, `calendars`, `queries`, `operations`, `parse`, `format`,
`index`. Consumers import only from `$lib/util/dias`.
- All date-related `Intl` consolidated in `dias/format.ts` —
`DateFormatter`, cache, `resolveDateOrder`, `resolveHourCycle`,
placeholders, defaults.
- `ext/dates` now a thin reactive wrapper delegating to `dias`.
- Aligned App-layer `HourCycle` to canonical numeric form `12 | 24`
(matches `Intl.DateTimeFormat`'s `hour12`). Removed string form
`'12h' | '24h'` from `ext/app/types`, `ext/dates`,
`ext/presentation/locale-defaults`, and their tests.
- Repointed every consumer: `soma/external/dates`,
`terra/external/dates`, eight `routes/test/*` pages.
- Legacy `src/lib/util/dates/` left untouched by request.
**Tier 3 components**
- `soma/components/calendar/` — 14 parts, single + multiple selection,
`MonthSelect`/`YearSelect`, ISO/simple week numbers,
`isDateHoliday` matcher, `data-weekend` flag, navigation live-
region, RTL flip, full ARIA, 27-item checklist verified.
- `soma/components/range-calendar/` — 14 parts, range selection with
live hover preview (novel vs ark/bits/radix/react-aria), `minDays`
/ `maxDays` / `allowSingleDay`, third-click deselects only the
clicked endpoint.
- Test pages at `/test/soma/calendar` and `/test/soma/range-calendar`
with seven demos each. Links added to the soma index under a new
"Dates" section.
- READMEs with anatomy, parts, props, ARIA, keyboard, data-attrs, and
a competitive comparison table.
**Command fixes**
- Resolved O(N^2) reactive cascade: introduced
`visibleSet: $derived<Set<string>>` on the root provider;
per-item `isVisible` is now an O(1) `has()` lookup instead of
calling back into the provider, which was re-running all items'
derivations on every `itemsVersion` bump.
- Added `dir` prop with fallback to `soma.presentation.getDir()`;
horizontal arrows flip in RTL via `getDirectionalKeys`; root
receives `dir` attribute.
**Doc updates (session outcomes)**
- `CLAUDE.md`: replaced obsolete `@/glob/lib` date references with
`$lib/util/dias`; added canonical date-layer section; reinforced
`Provider` export rule and `data-{component}[-{part}]` naming
(never `data-soma-*`); clarified translation convention.
- `src/uix/soma/COMPONENT_GUIDE.md`: new checklist items 26
(component README required) and 27 (grep for data-attr
consistency); new Common Mistakes 11 (`data-soma-*` prefix), 12
(wrong date module), 13 (string `HourCycle`).
- `src/uix/soma/SOMA_ARCHITECTURE.md`: clarified data-attr naming
(canonical emitter is `createAttrs`; validator checks enum
values only, not names); new section covering date types and
formatting through `$soma/external/dates` → `$lib/util/dias`;
documented numeric `HourCycle`.
**Infrastructure**
- `PrimitiveHeaderAttributes` and `PrimitiveSelectAttributes` added
to `$soma/types`.
- `getLastFirstDayOfWeek`, `getNextLastDayOfWeek` re-exported from
`$soma/external/dates`.
- `calendar.*` and `range-calendar.*` translation blocks added to
`$soma/core/langs.ts`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
## 4. Goal-driven execution
soma: dias date library, Calendar + RangeCalendar, Command fixes, doc updates
**Date library reorganisation** (no new third-party dependency)
- New `src/lib/util/dias/` with `_vendor/` (Adobe Apache 2.0 vendored code,
ATTRIBUTION.md preserved) and a public facade split into `types`,
`values`, `calendars`, `queries`, `operations`, `parse`, `format`,
`index`. Consumers import only from `$lib/util/dias`.
- All date-related `Intl` consolidated in `dias/format.ts` —
`DateFormatter`, cache, `resolveDateOrder`, `resolveHourCycle`,
placeholders, defaults.
- `ext/dates` now a thin reactive wrapper delegating to `dias`.
- Aligned App-layer `HourCycle` to canonical numeric form `12 | 24`
(matches `Intl.DateTimeFormat`'s `hour12`). Removed string form
`'12h' | '24h'` from `ext/app/types`, `ext/dates`,
`ext/presentation/locale-defaults`, and their tests.
- Repointed every consumer: `soma/external/dates`,
`terra/external/dates`, eight `routes/test/*` pages.
- Legacy `src/lib/util/dates/` left untouched by request.
**Tier 3 components**
- `soma/components/calendar/` — 14 parts, single + multiple selection,
`MonthSelect`/`YearSelect`, ISO/simple week numbers,
`isDateHoliday` matcher, `data-weekend` flag, navigation live-
region, RTL flip, full ARIA, 27-item checklist verified.
- `soma/components/range-calendar/` — 14 parts, range selection with
live hover preview (novel vs ark/bits/radix/react-aria), `minDays`
/ `maxDays` / `allowSingleDay`, third-click deselects only the
clicked endpoint.
- Test pages at `/test/soma/calendar` and `/test/soma/range-calendar`
with seven demos each. Links added to the soma index under a new
"Dates" section.
- READMEs with anatomy, parts, props, ARIA, keyboard, data-attrs, and
a competitive comparison table.
**Command fixes**
- Resolved O(N^2) reactive cascade: introduced
`visibleSet: $derived<Set<string>>` on the root provider;
per-item `isVisible` is now an O(1) `has()` lookup instead of
calling back into the provider, which was re-running all items'
derivations on every `itemsVersion` bump.
- Added `dir` prop with fallback to `soma.presentation.getDir()`;
horizontal arrows flip in RTL via `getDirectionalKeys`; root
receives `dir` attribute.
**Doc updates (session outcomes)**
- `CLAUDE.md`: replaced obsolete `@/glob/lib` date references with
`$lib/util/dias`; added canonical date-layer section; reinforced
`Provider` export rule and `data-{component}[-{part}]` naming
(never `data-soma-*`); clarified translation convention.
- `src/uix/soma/COMPONENT_GUIDE.md`: new checklist items 26
(component README required) and 27 (grep for data-attr
consistency); new Common Mistakes 11 (`data-soma-*` prefix), 12
(wrong date module), 13 (string `HourCycle`).
- `src/uix/soma/SOMA_ARCHITECTURE.md`: clarified data-attr naming
(canonical emitter is `createAttrs`; validator checks enum
values only, not names); new section covering date types and
formatting through `$soma/external/dates` → `$lib/util/dias`;
documented numeric `HourCycle`.
**Infrastructure**
- `PrimitiveHeaderAttributes` and `PrimitiveSelectAttributes` added
to `$soma/types`.
- `getLastFirstDayOfWeek`, `getNextLastDayOfWeek` re-exported from
`$soma/external/dates`.
- `calendar.*` and `range-calendar.*` translation blocks added to
`$soma/core/langs.ts`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
Define success criteria. Loop until verified.
soma: dias date library, Calendar + RangeCalendar, Command fixes, doc updates
**Date library reorganisation** (no new third-party dependency)
- New `src/lib/util/dias/` with `_vendor/` (Adobe Apache 2.0 vendored code,
ATTRIBUTION.md preserved) and a public facade split into `types`,
`values`, `calendars`, `queries`, `operations`, `parse`, `format`,
`index`. Consumers import only from `$lib/util/dias`.
- All date-related `Intl` consolidated in `dias/format.ts` —
`DateFormatter`, cache, `resolveDateOrder`, `resolveHourCycle`,
placeholders, defaults.
- `ext/dates` now a thin reactive wrapper delegating to `dias`.
- Aligned App-layer `HourCycle` to canonical numeric form `12 | 24`
(matches `Intl.DateTimeFormat`'s `hour12`). Removed string form
`'12h' | '24h'` from `ext/app/types`, `ext/dates`,
`ext/presentation/locale-defaults`, and their tests.
- Repointed every consumer: `soma/external/dates`,
`terra/external/dates`, eight `routes/test/*` pages.
- Legacy `src/lib/util/dates/` left untouched by request.
**Tier 3 components**
- `soma/components/calendar/` — 14 parts, single + multiple selection,
`MonthSelect`/`YearSelect`, ISO/simple week numbers,
`isDateHoliday` matcher, `data-weekend` flag, navigation live-
region, RTL flip, full ARIA, 27-item checklist verified.
- `soma/components/range-calendar/` — 14 parts, range selection with
live hover preview (novel vs ark/bits/radix/react-aria), `minDays`
/ `maxDays` / `allowSingleDay`, third-click deselects only the
clicked endpoint.
- Test pages at `/test/soma/calendar` and `/test/soma/range-calendar`
with seven demos each. Links added to the soma index under a new
"Dates" section.
- READMEs with anatomy, parts, props, ARIA, keyboard, data-attrs, and
a competitive comparison table.
**Command fixes**
- Resolved O(N^2) reactive cascade: introduced
`visibleSet: $derived<Set<string>>` on the root provider;
per-item `isVisible` is now an O(1) `has()` lookup instead of
calling back into the provider, which was re-running all items'
derivations on every `itemsVersion` bump.
- Added `dir` prop with fallback to `soma.presentation.getDir()`;
horizontal arrows flip in RTL via `getDirectionalKeys`; root
receives `dir` attribute.
**Doc updates (session outcomes)**
- `CLAUDE.md`: replaced obsolete `@/glob/lib` date references with
`$lib/util/dias`; added canonical date-layer section; reinforced
`Provider` export rule and `data-{component}[-{part}]` naming
(never `data-soma-*`); clarified translation convention.
- `src/uix/soma/COMPONENT_GUIDE.md`: new checklist items 26
(component README required) and 27 (grep for data-attr
consistency); new Common Mistakes 11 (`data-soma-*` prefix), 12
(wrong date module), 13 (string `HourCycle`).
- `src/uix/soma/SOMA_ARCHITECTURE.md`: clarified data-attr naming
(canonical emitter is `createAttrs`; validator checks enum
values only, not names); new section covering date types and
formatting through `$soma/external/dates` → `$lib/util/dias`;
documented numeric `HourCycle`.
**Infrastructure**
- `PrimitiveHeaderAttributes` and `PrimitiveSelectAttributes` added
to `$soma/types`.
- `getLastFirstDayOfWeek`, `getNextLastDayOfWeek` re-exported from
`$soma/external/dates`.
- `calendar.*` and `range-calendar.*` translation blocks added to
`$soma/core/langs.ts`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
- "Add validation" → "Write tests for invalid inputs, then make them pass."
- "Fix the bug" → "Write a test that reproduces it, then make it pass."
- "Refactor X" → "Ensure tests pass before and after."
soma: dias date library, Calendar + RangeCalendar, Command fixes, doc updates
**Date library reorganisation** (no new third-party dependency)
- New `src/lib/util/dias/` with `_vendor/` (Adobe Apache 2.0 vendored code,
ATTRIBUTION.md preserved) and a public facade split into `types`,
`values`, `calendars`, `queries`, `operations`, `parse`, `format`,
`index`. Consumers import only from `$lib/util/dias`.
- All date-related `Intl` consolidated in `dias/format.ts` —
`DateFormatter`, cache, `resolveDateOrder`, `resolveHourCycle`,
placeholders, defaults.
- `ext/dates` now a thin reactive wrapper delegating to `dias`.
- Aligned App-layer `HourCycle` to canonical numeric form `12 | 24`
(matches `Intl.DateTimeFormat`'s `hour12`). Removed string form
`'12h' | '24h'` from `ext/app/types`, `ext/dates`,
`ext/presentation/locale-defaults`, and their tests.
- Repointed every consumer: `soma/external/dates`,
`terra/external/dates`, eight `routes/test/*` pages.
- Legacy `src/lib/util/dates/` left untouched by request.
**Tier 3 components**
- `soma/components/calendar/` — 14 parts, single + multiple selection,
`MonthSelect`/`YearSelect`, ISO/simple week numbers,
`isDateHoliday` matcher, `data-weekend` flag, navigation live-
region, RTL flip, full ARIA, 27-item checklist verified.
- `soma/components/range-calendar/` — 14 parts, range selection with
live hover preview (novel vs ark/bits/radix/react-aria), `minDays`
/ `maxDays` / `allowSingleDay`, third-click deselects only the
clicked endpoint.
- Test pages at `/test/soma/calendar` and `/test/soma/range-calendar`
with seven demos each. Links added to the soma index under a new
"Dates" section.
- READMEs with anatomy, parts, props, ARIA, keyboard, data-attrs, and
a competitive comparison table.
**Command fixes**
- Resolved O(N^2) reactive cascade: introduced
`visibleSet: $derived<Set<string>>` on the root provider;
per-item `isVisible` is now an O(1) `has()` lookup instead of
calling back into the provider, which was re-running all items'
derivations on every `itemsVersion` bump.
- Added `dir` prop with fallback to `soma.presentation.getDir()`;
horizontal arrows flip in RTL via `getDirectionalKeys`; root
receives `dir` attribute.
**Doc updates (session outcomes)**
- `CLAUDE.md`: replaced obsolete `@/glob/lib` date references with
`$lib/util/dias`; added canonical date-layer section; reinforced
`Provider` export rule and `data-{component}[-{part}]` naming
(never `data-soma-*`); clarified translation convention.
- `src/uix/soma/COMPONENT_GUIDE.md`: new checklist items 26
(component README required) and 27 (grep for data-attr
consistency); new Common Mistakes 11 (`data-soma-*` prefix), 12
(wrong date module), 13 (string `HourCycle`).
- `src/uix/soma/SOMA_ARCHITECTURE.md`: clarified data-attr naming
(canonical emitter is `createAttrs`; validator checks enum
values only, not names); new section covering date types and
formatting through `$soma/external/dates` → `$lib/util/dias`;
documented numeric `HourCycle`.
**Infrastructure**
- `PrimitiveHeaderAttributes` and `PrimitiveSelectAttributes` added
to `$soma/types`.
- `getLastFirstDayOfWeek`, `getNextLastDayOfWeek` re-exported from
`$soma/external/dates`.
- `calendar.*` and `range-calendar.*` translation blocks added to
`$soma/core/langs.ts`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
cleanup phase D: rewrite CLAUDE.md to reflect new architecture
Drops references to terra/air/lib (deleted in phases A-B). New
architecture section: arts/libs/svrs at the runtime + helper layer;
uix/{morfo, sema, soma, eidos, active-uix} at the UI layer, with
morfo as the cross-layer contract (compileMorfo + cached
contracts.cssSelectors). Path-alias table updated to match
svelte.config.js / vite.config.ts after phase C. Build/test commands
point at the new test paths.
Critical-rules block: drop "NEVER modify terra source code" (terra is
gone) and the soma-audit references (legacy markdown). Keep "NEVER
delete files without explicit instruction" — this cleanup happened
under explicit user direction, the rule still holds.
Auto-memory in ~/.claude/projects/...: dropped feedback_terra_readonly,
feedback_air_wrapper_children, feedback_follow_terra_patterns,
feedback_architecture_fidelity, feedback_layout_kills_outlines (refs
deleted src/routes/layout.css), feedback_check_dias_before_porting
(consolidated into feedback_date_library), project_terra_air_dead,
project_session_state, project_activeapp_refactor. Added
project_active_uix_cleanup with the new state. Updated
feedback_date_library to point at \$libs/days.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
Strong success criteria let you loop independently. Weak criteria require
constant clarification.