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

8.2 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

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

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
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
npm run lint         # Check formatting (Prettier)
npm run format       # Auto-format

Code Style

  • 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

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, $connection, $format, $frontend, $http, $lang, $logger, $orca, $perm, $prefs, $session, $sium, $storage, $timer src/arts/{name}
$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:

  • client: Browser tests via Playwright for *.svelte.{test,spec}.{js,ts}.
  • server: Node environment for *.{test,spec}.{js,ts} (excludes svelte tests).

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.

arts/   → runtime artifacts: active-app, adom, perm, prefs, ...
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

morfo (src/uix/morfo/)

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)

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.

eidos linter

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

  • 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.

Critical Rules

  • 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.

Refactor Documents

In-progress design notes for the kernel rewrite live in src/uix/refactor_claude.md and src/uix/refactor_code.md. Read them before making architectural changes to soma / sema / morfo so you don't re-litigate decisions already taken.


Behavioral Guidelines

These reduce common LLM coding mistakes. They bias toward caution over speed — for trivial tasks, use judgment.

1. Think before coding

Don't assume. Don't hide confusion. Surface tradeoffs.

  • State assumptions explicitly. If uncertain, ask.
  • If multiple interpretations exist, present them — don't pick silently.
  • If a simpler approach exists, say so. Push back when warranted.
  • If something is unclear, stop. Name what's confusing. Ask.

2. Simplicity first

Minimum code that solves the problem. Nothing speculative.

  • 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.

3. Surgical changes

Touch only what you must. Clean up only your own mess.

  • 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.
  • If you notice unrelated dead code, mention it — don't delete it.

When your changes create orphans, remove the imports / variables / functions your changes made unused. Don't remove pre-existing dead code unless asked.

4. Goal-driven execution

Define success criteria. Loop until verified.

  • "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."

Strong success criteria let you loop independently. Weak criteria require constant clarification.

Powered by TurnKey Linux.