@cascivo/mcp 0.1.5 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -793,7 +793,8 @@ function createServer(options = {}) {
793
793
  "layout",
794
794
  "block",
795
795
  "chart",
796
- "flow"
796
+ "flow",
797
+ "editor"
797
798
  ]).optional().describe("Filter by entry type")
798
799
  }
799
800
  }, ({ category, type }) => json(listComponents(registry, category, type)));
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["HERE","c","v","HERE","HERE"],"sources":["../src/registry.ts","../src/theme.ts","../src/scaffold.ts","../src/validate.ts","../src/grammar.ts","../src/scaffold-view.ts","../src/prompt.ts","../src/tokens.ts","../src/variants.ts","../src/validate-component.ts","../src/context.ts","../src/select.ts","../src/server.ts","../src/index.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nexport interface PropManifest {\n name: string\n type: string\n required: boolean\n default?: string\n description?: string\n}\n\nexport interface ComponentManifest {\n name: string\n description: string\n category: string\n states: string[]\n variants: string[]\n sizes: string[]\n props: PropManifest[]\n tokens: string[]\n accessibility: { role: string; wcag: string; keyboard: string[] }\n examples: { title: string; code: string; description?: string }[]\n dependencies: string[]\n tags: string[]\n}\n\nexport interface RegistryComponent {\n name: string\n type?: 'component' | 'layout' | 'block' | 'chart' | 'section' | 'flow'\n description: string\n category: string\n version: string\n files: string[]\n dependencies: string[]\n tags: string[]\n meta: ComponentManifest\n}\n\nexport interface Registry {\n version: string\n generatedAt: string\n components: RegistryComponent[]\n}\n\nconst HERE = dirname(fileURLToPath(import.meta.url))\n\n/**\n * Resolve the registry.json location. Checks, in order: an explicit path, the\n * `CASCIVO_REGISTRY_PATH` env var, a copy bundled next to the built server\n * (published package), and the monorepo root (dev).\n */\nexport function resolveRegistryPath(explicit?: string): string {\n const candidates = [\n explicit,\n process.env.CASCIVO_REGISTRY_PATH,\n join(HERE, 'registry.json'),\n join(HERE, '..', '..', '..', 'registry.json'),\n join(HERE, '..', '..', 'registry.json'),\n ].filter((p): p is string => typeof p === 'string' && p.length > 0)\n\n return (\n candidates.find((p) => existsSync(p)) ?? candidates[candidates.length - 1] ?? 'registry.json'\n )\n}\n\nexport function loadRegistry(path?: string): Registry {\n const resolved = resolveRegistryPath(path)\n const raw = JSON.parse(readFileSync(resolved, 'utf8')) as Registry\n if (!Array.isArray(raw.components)) {\n throw new Error(`Invalid registry at ${resolved}: \"components\" must be an array`)\n }\n return raw\n}\n\n/** List component manifests, optionally filtered by category and/or type. */\nexport function listComponents(\n registry: Registry,\n category?: string,\n type?: string,\n): ComponentManifest[] {\n let entries = registry.components\n if (category) entries = entries.filter((c) => c.category === category)\n if (type) entries = entries.filter((c) => c.type === type)\n return entries.map((c) => c.meta)\n}\n\n/** Find one component manifest by name (matches registry name or meta name). */\nexport function getComponent(registry: Registry, name: string): ComponentManifest | undefined {\n const target = name.toLowerCase()\n return registry.components.find(\n (c) => c.name.toLowerCase() === target || c.meta.name.toLowerCase() === target,\n )?.meta\n}\n\n// ---------------------------------------------------------------------------\n// Multi-registry support\n// ---------------------------------------------------------------------------\n\nexport interface RegistryDirectoryEntry {\n namespace: string\n name: string\n description?: string\n registryUrl: string\n verified?: boolean\n homepage?: string\n}\n\nconst DIRECTORY_URL = 'https://cascivo.com/r/registries.json'\nconst FETCH_TIMEOUT_MS = 15_000\nconst MAX_BODY_BYTES = 1_048_576 // 1 MB\n\ntype FetchFn = (url: string, init?: RequestInit) => Promise<Response>\n\nasync function fetchWithGuards(url: string, fetchFn: FetchFn = fetch): Promise<string | null> {\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS)\n try {\n const res = await fetchFn(url, { signal: controller.signal })\n if (!res.ok) return null\n const buf = await res.arrayBuffer()\n if (buf.byteLength > MAX_BODY_BYTES) return null\n return new TextDecoder().decode(buf)\n } catch {\n return null\n } finally {\n clearTimeout(timer)\n }\n}\n\n/** Fetch the central cascade registry directory. Returns empty array on failure. */\nexport async function fetchDirectory(fetchFn?: FetchFn): Promise<RegistryDirectoryEntry[]> {\n const raw = await fetchWithGuards(DIRECTORY_URL, fetchFn)\n if (!raw) return []\n try {\n const parsed = JSON.parse(raw) as unknown\n if (!Array.isArray(parsed)) return []\n return parsed as RegistryDirectoryEntry[]\n } catch {\n return []\n }\n}\n\n/** Fetch the component index from a namespace's registryUrl. Returns null on failure. */\nexport async function fetchRegistryIndex(\n registryUrl: string,\n fetchFn?: FetchFn,\n): Promise<Registry | null> {\n // Resolve the registry.json URL: replace trailing `{name}` template or append /registry.json\n const indexUrl = registryUrl.includes('{name}')\n ? registryUrl.replace('{name}', 'registry').replace(/\\/registry$/, '/registry.json')\n : registryUrl.replace(/\\/?$/, '/registry.json').replace(/\\/\\/registry\\.json$/, '/registry.json')\n const raw = await fetchWithGuards(indexUrl, fetchFn)\n if (!raw) return null\n try {\n const parsed = JSON.parse(raw) as Registry\n if (!Array.isArray(parsed.components)) return null\n return parsed\n } catch {\n return null\n }\n}\n\n/** Parse CASCADE_REGISTRIES env var — returns empty array on failure. */\nexport function getEnvRegistries(): RegistryDirectoryEntry[] {\n const raw = process.env['CASCADE_REGISTRIES']\n if (!raw) return []\n try {\n const parsed = JSON.parse(raw) as unknown\n if (!Array.isArray(parsed)) return []\n return parsed as RegistryDirectoryEntry[]\n } catch {\n return []\n }\n}\n\n/** Merge directory entries with env entries (env wins on namespace collision). */\nexport function mergeRegistries(\n directory: RegistryDirectoryEntry[],\n env: RegistryDirectoryEntry[],\n): RegistryDirectoryEntry[] {\n const map = new Map<string, RegistryDirectoryEntry>()\n for (const entry of directory) map.set(entry.namespace, entry)\n for (const entry of env) map.set(entry.namespace, entry)\n return Array.from(map.values())\n}\n\n/** Fuzzy search over name, tags, and description. */\nexport function searchComponents(registry: Registry, query: string): ComponentManifest[] {\n const q = query.toLowerCase().trim()\n if (q === '') return []\n return registry.components\n .filter(\n (c) =>\n c.name.toLowerCase().includes(q) ||\n c.description.toLowerCase().includes(q) ||\n c.tags.some((t) => t.toLowerCase().includes(q)),\n )\n .map((c) => c.meta)\n}\n","export interface ThemeColors {\n /** Main brand / interactive color (maps to the accent token family). */\n primary: string\n /** Base gray used to derive surfaces, borders, and text. */\n neutral: string\n /** Secondary highlight color (info / focus ring). */\n accent: string\n}\n\n/** Darken a color by mixing in black (modern CSS, no preprocessor). */\nfunction darken(color: string, amount: number): string {\n return `color-mix(in oklab, ${color}, black ${amount}%)`\n}\n\n/** Lighten a color by mixing in white. */\nfunction lighten(color: string, amount: number): string {\n return `color-mix(in oklab, ${color}, white ${amount}%)`\n}\n\n/**\n * Generate a custom cascivo theme as CSS. Maps the three input colors onto the\n * semantic token layer; component tokens inherit automatically.\n */\nexport function generateThemeCss(colors: ThemeColors, name = 'custom'): string {\n const { primary, neutral, accent } = colors\n return `/* cascivo — Generated theme: ${name} */\n\n@layer cascivo.theme {\n [data-theme='${name}'] {\n color-scheme: light;\n\n /* ── Surface (derived from neutral) ───────────────── */\n --cascivo-color-bg: ${lighten(neutral, 96)};\n --cascivo-color-bg-subtle: ${lighten(neutral, 92)};\n --cascivo-color-surface: ${lighten(neutral, 98)};\n --cascivo-color-surface-raised: ${lighten(neutral, 94)};\n --cascivo-color-surface-overlay: ${lighten(neutral, 98)};\n --cascivo-color-border: ${lighten(neutral, 80)};\n --cascivo-color-border-strong: ${lighten(neutral, 65)};\n\n /* ── Text (derived from neutral) ──────────────────── */\n --cascivo-color-text: ${darken(neutral, 80)};\n --cascivo-color-text-subtle: ${darken(neutral, 50)};\n --cascivo-color-text-muted: ${lighten(neutral, 30)};\n --cascivo-color-text-on-accent: #ffffff;\n --cascivo-color-text-on-destructive: #ffffff;\n\n /* ── Accent / primary interactive ─────────────────── */\n --cascivo-color-accent: ${primary};\n --cascivo-color-accent-hover: ${darken(primary, 12)};\n --cascivo-color-accent-active: ${darken(primary, 24)};\n --cascivo-color-accent-subtle: ${lighten(primary, 88)};\n --cascivo-color-accent-muted: ${lighten(primary, 76)};\n\n /* ── Secondary accent (info / focus) ──────────────── */\n --cascivo-color-info: ${accent};\n --cascivo-color-info-subtle: ${lighten(accent, 88)};\n --cascivo-color-focus-ring: ${accent};\n --cascivo-focus-ring: 0 0 0 3px ${lighten(accent, 20)};\n\n /* ── Status ───────────────────────────────────────── */\n --cascivo-color-destructive: #dc2626;\n --cascivo-color-destructive-hover: ${darken('#dc2626', 12)};\n --cascivo-color-destructive-subtle: ${lighten('#dc2626', 88)};\n --cascivo-color-success: #16a34a;\n --cascivo-color-success-subtle: ${lighten('#16a34a', 88)};\n --cascivo-color-warning: #f59e0b;\n --cascivo-color-warning-subtle: ${lighten('#f59e0b', 88)};\n }\n}\n`\n}\n","export interface ScaffoldOptions {\n description: string\n components?: string[]\n}\n\nconst DEFAULT_COMPONENTS = ['card', 'input', 'button']\n\nfunction pascalCase(name: string): string {\n return name\n .split(/[-_\\s]+/)\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join('')\n}\n\n/** A reasonable default usage snippet per component for the scaffold. */\nfunction usage(component: string, Tag: string): string {\n switch (component) {\n case 'button':\n return ` <${Tag}>Get started</${Tag}>`\n case 'input':\n return ` <${Tag} label=\"Email\" placeholder=\"you@example.com\" />`\n case 'card':\n return ` <${Tag}>\\n <h2>Card title</h2>\\n <p>Card content goes here.</p>\\n </${Tag}>`\n case 'badge':\n return ` <${Tag}>New</${Tag}>`\n default:\n return ` <${Tag} />`\n }\n}\n\n/**\n * Generate a JSX page layout string from a natural-language description and an\n * optional list of cascade components to include.\n */\nexport function scaffoldPage(options: ScaffoldOptions): string {\n const components = options.components?.length ? options.components : DEFAULT_COMPONENTS\n const unique = [...new Set(components.map((c) => c.toLowerCase()))]\n\n const imports = unique\n .map((c) => `import { ${pascalCase(c)} } from './components/ui/${c}/${c}'`)\n .join('\\n')\n\n const body = unique.map((c) => usage(c, pascalCase(c))).join('\\n')\n\n return `${imports}\n\n/* ${options.description} */\nexport function Page() {\n return (\n <main\n data-theme=\"light\"\n style={{ maxWidth: '48rem', margin: '0 auto', padding: '2rem', display: 'grid', gap: '1rem' }}\n >\n${body}\n </main>\n )\n}\n`\n}\n","// Inlined from @cascivo/render — avoids a Node.js binary depending on React components at runtime.\n// Component name validation uses the registry (passed by caller) instead of the React component map.\n\nexport interface ValidationError {\n path: string\n message: string\n}\n\nexport interface ComponentNode {\n component: string\n props?: Record<string, unknown>\n bind?: Record<string, string>\n events?: Record<string, string>\n children?: ComponentNode[] | string\n}\n\nexport interface ViewConfig {\n $schema?: string\n version?: 1\n view: {\n layout?: string\n regions: Record<string, ComponentNode[]>\n }\n}\n\nconst DATA_REF_RE = /^\\$data\\./\nconst ACTION_REF_RE = /^\\$actions\\./\n\nfunction closestName(name: string, candidates: string[]): string | undefined {\n const target = name.toLowerCase()\n let best: string | undefined\n let bestDist = 3\n for (const candidate of candidates) {\n const dist = levenshtein(target, candidate.toLowerCase())\n if (dist < bestDist) {\n bestDist = dist\n best = candidate\n }\n }\n return best\n}\n\nfunction levenshtein(a: string, b: string): number {\n const m = a.length\n const n = b.length\n const dp: number[][] = Array.from({ length: m + 1 }, (_, i) =>\n Array.from({ length: n + 1 }, (_, j) => (i === 0 ? j : j === 0 ? i : 0)),\n )\n for (let i = 1; i <= m; i++) {\n for (let j = 1; j <= n; j++) {\n dp[i]![j] =\n a[i - 1] === b[j - 1]\n ? dp[i - 1]![j - 1]!\n : 1 + Math.min(dp[i - 1]![j]!, dp[i]![j - 1]!, dp[i - 1]![j - 1]!)\n }\n }\n return dp[m]![n]!\n}\n\nfunction validateNode(\n node: unknown,\n path: string,\n errors: ValidationError[],\n componentNames: Set<string>,\n): void {\n if (typeof node !== 'object' || node === null) {\n errors.push({ path, message: 'Expected a component node object' })\n return\n }\n const n = node as Record<string, unknown>\n if (typeof n['component'] !== 'string') {\n errors.push({ path: `${path}.component`, message: 'component must be a string' })\n return\n }\n const componentName = n['component'] as string\n if (!componentNames.has(componentName)) {\n const suggestion = closestName(componentName, [...componentNames])\n const hint = suggestion ? ` Did you mean \"${suggestion}\"?` : ''\n errors.push({\n path: `${path}.component`,\n message: `Unknown component \"${componentName}\".${hint}`,\n })\n return\n }\n\n const nodeBind = (n['bind'] ?? {}) as Record<string, string>\n for (const [key, value] of Object.entries(nodeBind)) {\n if (typeof value !== 'string' || !DATA_REF_RE.test(value)) {\n errors.push({\n path: `${path}.bind.${key}`,\n message: `bind values must start with \"$data.\" — got \"${value}\"`,\n })\n }\n }\n\n const nodeEvents = (n['events'] ?? {}) as Record<string, string>\n for (const [key, value] of Object.entries(nodeEvents)) {\n if (typeof value !== 'string' || !ACTION_REF_RE.test(value)) {\n errors.push({\n path: `${path}.events.${key}`,\n message: `events values must start with \"$actions.\" — got \"${value}\"`,\n })\n }\n }\n\n if (Array.isArray(n['children'])) {\n for (let i = 0; i < n['children'].length; i++) {\n validateNode(\n n['children'][i] as ComponentNode,\n `${path}.children[${i}]`,\n errors,\n componentNames,\n )\n }\n }\n}\n\n/** Validate a ViewConfig object. Component names are checked against the provided set. */\nexport function validateView(\n config: unknown,\n componentNames: Set<string>,\n): { valid: boolean; errors: ValidationError[] } {\n const errors: ValidationError[] = []\n\n if (typeof config !== 'object' || config === null) {\n return { valid: false, errors: [{ path: '', message: 'Config must be an object' }] }\n }\n\n const c = config as Record<string, unknown>\n const view = c['view']\n\n if (typeof view !== 'object' || view === null) {\n return { valid: false, errors: [{ path: 'view', message: 'view must be an object' }] }\n }\n\n const v = view as Record<string, unknown>\n const regions = v['regions']\n\n if (typeof regions !== 'object' || regions === null) {\n errors.push({ path: 'view.regions', message: 'view.regions must be an object' })\n return { valid: false, errors }\n }\n\n for (const [regionName, nodes] of Object.entries(regions as Record<string, unknown>)) {\n if (!Array.isArray(nodes)) {\n errors.push({\n path: `view.regions.${regionName}`,\n message: `Region \"${regionName}\" must be an array of component nodes`,\n })\n continue\n }\n for (let i = 0; i < nodes.length; i++) {\n validateNode(\n nodes[i] as ComponentNode,\n `view.regions.${regionName}[${i}]`,\n errors,\n componentNames,\n )\n }\n }\n\n return { valid: errors.length === 0, errors }\n}\n","// Library-derived bound vocabulary (v40 T1).\n//\n// OpenUI's anti-hallucination mechanism is a system prompt generated from the\n// component library so a model can only emit registered components/props. This\n// module derives that bound vocabulary from the cascade manifests\n// (component.meta.ts → registry.json): per component → its props (name, type,\n// allowed enum values, required) plus variants/sizes. Because it is *derived*,\n// it can never drift from the components (grammar.test.ts asserts every name it\n// references exists in the registry).\n\nimport type { Registry } from './registry.js'\n\nexport interface GrammarProp {\n name: string\n required: boolean\n /** Raw TypeScript type string from the manifest. */\n type: string\n /** Allowed values, when `type` is a string-literal union (e.g. `'sm' | 'md'`). */\n enum?: string[]\n}\n\nexport interface GrammarComponent {\n name: string\n category: string\n props: GrammarProp[]\n variants: string[]\n sizes: string[]\n}\n\nexport interface ViewGrammar {\n components: GrammarComponent[]\n}\n\n/**\n * Parse a string-literal union type (`'a' | 'b' | \"c\"`) into its allowed\n * values. Returns `undefined` for any non-enum type (primitives, functions,\n * named types, object shapes) so the grammar only constrains what it can.\n */\nexport function parseEnum(type: string): string[] | undefined {\n const branches = type\n .split('|')\n .map((s) => s.trim())\n .filter((s) => s.length > 0)\n if (branches.length === 0) return undefined\n const values: string[] = []\n for (const branch of branches) {\n const quoted = branch.match(/^['\"](.+)['\"]$/)\n if (!quoted?.[1]) return undefined\n values.push(quoted[1])\n }\n return values\n}\n\n/**\n * Build the bound-vocabulary descriptor from the registry, optionally scoped to\n * a subset of component names (case-insensitive). Output is deterministic\n * (components and props sorted by name) for reproducible prompts and tests.\n */\n// Preference when two registry entries share a meta.name (e.g. a `component`\n// and a `layout` both named \"AppShell\"): the node-usable component wins.\nconst TYPE_RANK: Record<string, number> = {\n component: 0,\n block: 1,\n chart: 2,\n section: 3,\n layout: 4,\n}\n\nexport function buildGrammar(registry: Registry, subset?: string[]): ViewGrammar {\n const wanted = subset && subset.length > 0 ? new Set(subset.map((n) => n.toLowerCase())) : null\n\n // Dedupe by meta.name, keeping the highest-ranked (node-usable) entry.\n const canonical = new Map<string, (typeof registry.components)[number]>()\n for (const c of registry.components) {\n const key = c.meta.name.toLowerCase()\n const current = canonical.get(key)\n if (!current || (TYPE_RANK[c.type ?? ''] ?? 9) < (TYPE_RANK[current.type ?? ''] ?? 9)) {\n canonical.set(key, c)\n }\n }\n\n const components: GrammarComponent[] = [...canonical.values()]\n .filter(\n (c) => !wanted || wanted.has(c.meta.name.toLowerCase()) || wanted.has(c.name.toLowerCase()),\n )\n .map((c) => {\n const props: GrammarProp[] = (c.meta.props ?? [])\n .map((p) => {\n const values = parseEnum(p.type)\n return {\n name: p.name,\n required: p.required === true,\n type: p.type,\n ...(values ? { enum: values } : {}),\n }\n })\n .sort((a, b) => a.name.localeCompare(b.name))\n return {\n name: c.meta.name,\n category: c.category,\n props,\n variants: c.meta.variants ?? [],\n sizes: c.meta.sizes ?? [],\n }\n })\n .sort((a, b) => a.name.localeCompare(b.name))\n\n return { components }\n}\n\n/** Render one prop as `name`, `name*` (required), with enum choices or its type. */\nfunction formatProp(prop: GrammarProp): string {\n const mark = prop.required ? '*' : ''\n const value = prop.enum ? prop.enum.join('|') : prop.type\n return `${prop.name}${mark}: ${value}`\n}\n\n/**\n * Render the grammar as a compact, model-friendly table: one line per\n * component. Terser than verbose JSON; a `*` marks a required prop.\n *\n * Badge(size: sm|md, variant: default|secondary|success|warning|destructive|outline)\n */\nexport function formatGrammar(grammar: ViewGrammar): string {\n return grammar.components\n .map((c) => `${c.name}(${c.props.map(formatProp).join(', ')})`)\n .join('\\n')\n}\n","import type { ViewConfig } from './validate.js'\nimport { validateView } from './validate.js'\nimport type { Registry } from './registry.js'\nimport { buildGrammar, formatGrammar } from './grammar.js'\n\ninterface ScaffoldViewInput {\n description: string\n components?: string[]\n}\n\n/** Simple keyword matcher — returns region layout name based on description keywords. */\nfunction pickLayout(description: string): string {\n const d = description.toLowerCase()\n if (d.includes('dashboard') || d.includes('stats') || d.includes('kpi')) return 'dashboard'\n if (d.includes('settings') || d.includes('preferences') || d.includes('config')) return 'settings'\n if (d.includes('login') || d.includes('auth') || d.includes('sign')) return 'auth'\n return 'none'\n}\n\n/** Pick sensible components from the registry matching keywords in description. */\nfunction pickComponents(description: string, registry: Registry, explicit?: string[]): string[] {\n if (explicit && explicit.length > 0) return explicit.map((c) => c.toLowerCase())\n const d = description.toLowerCase()\n const candidates: string[] = []\n for (const entry of registry.components) {\n const name = entry.meta.name.toLowerCase()\n const tags = entry.tags.join(' ').toLowerCase()\n if (d.includes(name) || tags.split(' ').some((t) => d.includes(t))) {\n candidates.push(entry.meta.name)\n }\n }\n // Always add at least one component\n if (candidates.length === 0) candidates.push('Badge')\n return candidates.slice(0, 4)\n}\n\nfunction makeNode(\n componentName: string,\n registry: Registry,\n): { component: string; props?: Record<string, string | number | boolean> } {\n const entry = registry.components.find(\n (c) => c.meta.name.toLowerCase() === componentName.toLowerCase(),\n )\n if (!entry) return { component: componentName }\n const props: Record<string, string | number | boolean> = {}\n for (const prop of entry.meta.props ?? []) {\n if (prop.required && prop.default !== undefined) {\n props[prop.name] = prop.default\n } else if (\n prop.default !== undefined &&\n ['string', 'number', 'boolean'].includes(typeof prop.default)\n ) {\n // Skip defaults that are complex\n }\n }\n return Object.keys(props).length > 0\n ? { component: entry.meta.name, props }\n : { component: entry.meta.name }\n}\n\nexport function scaffoldView(\n input: ScaffoldViewInput,\n registry: Registry,\n): {\n config: ViewConfig\n errors: { path: string; message: string }[]\n /** Bound-vocabulary grammar (v40 T1) for the scaffolded components, so a caller gets both a starter scaffold and the allowed props/enums to refine it. */\n grammar: string\n} {\n const layout = pickLayout(input.description)\n const componentNames = pickComponents(input.description, registry, input.components)\n\n const config: ViewConfig = {\n $schema:\n 'https://raw.githubusercontent.com/cascivo/cascivo/main/packages/render/schema/view.v1.json',\n version: 1,\n view: {\n ...(layout !== 'none' ? { layout } : {}),\n regions: {\n main: componentNames.map((name) => makeNode(name, registry)),\n },\n },\n }\n\n const validNames = new Set(registry.components.map((c) => c.meta.name))\n const { errors } = validateView(config, validNames)\n const grammar = formatGrammar(buildGrammar(registry, componentNames))\n return { config, errors, grammar }\n}\n","// Generation prompt derived from the bound vocabulary (v40 T1).\n//\n// Composes the system prompt an LLM needs to emit valid `ViewConfig` JSON that\n// is restricted to cascivo's real components, props, and enum values — the\n// OpenUI \"system prompt from the component library\" anti-hallucination\n// mechanism, applied to the format cascivo already ships and dogfoods\n// (@cascivo/render). See docs/ROADMAP-V40.md.\n\nimport { buildGrammar, formatGrammar } from './grammar.js'\nimport type { Registry } from './registry.js'\n\nexport interface GenerationPromptOptions {\n /** Scope the vocabulary to a subset of component names. Defaults to all. */\n components?: string[]\n}\n\nconst SCHEMA_DOC = `A ViewConfig is a JSON object:\n\n{\n \"version\": 1,\n \"view\": {\n \"layout\": \"<optional layout name, e.g. dashboard | settings | auth>\",\n \"regions\": {\n \"<regionName>\": [ <ComponentNode>, ... ]\n }\n }\n}\n\nA ComponentNode is:\n\n{\n \"component\": \"<one of the registered component names below>\",\n \"props\": { \"<propName>\": <value> },\n \"bind\": { \"<propName>\": \"$data.<path>\" },\n \"events\": { \"<eventPropName>\": \"$actions.<name>\" },\n \"children\": <ComponentNode[] | string | { \"$t\": \"<i18n.key>\" }>\n}\n\nRules:\n- \"component\" MUST be one of the registered components listed below — never invent one.\n- Only use props listed for that component; enum props MUST use one of the listed values.\n- \"bind\" values are host-data references and MUST start with \"$data.\".\n- \"events\" values are host-action references and MUST start with \"$actions.\".\n- \"children\" is an array of nodes, a plain string, or an i18n ref { \"$t\": \"key\" }.\n- Output ONLY the JSON ViewConfig — no prose, no markdown fences.`\n\n/**\n * Build the bound-vocabulary system prompt for emitting `ViewConfig` JSON.\n * Parameterizable by an optional component subset (defaults to the full\n * registry).\n */\nexport function buildGenerationPrompt(\n registry: Registry,\n options: GenerationPromptOptions = {},\n): string {\n const grammar = buildGrammar(registry, options.components)\n const vocabulary = formatGrammar(grammar)\n\n const sections = [\n 'You generate UI as a cascivo ViewConfig — a JSON description rendered by @cascivo/render <CascadeView />.',\n SCHEMA_DOC,\n 'Registered components (allowed vocabulary — `name*` marks a required prop):',\n vocabulary,\n // EXTENSION POINT (v40 T3, optional): when the `cvl` compact DSL ships, append a\n // \"cvl syntax\" section here so an agent can be asked to emit cvl instead of JSON.\n ]\n\n return sections.join('\\n\\n')\n}\n","import { existsSync, readFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nexport interface TokenCatalogEntry {\n name: string\n value: string\n layer: 'primitive' | 'semantic' | 'component'\n group: string\n resolvedDefault: string | null\n resolvesPerTheme: boolean\n}\n\nexport interface TokenCatalog {\n generatedAt: string\n count: number\n tokens: TokenCatalogEntry[]\n}\n\ntype FetchFn = (url: string, init?: RequestInit) => Promise<Response>\n\nconst HERE = dirname(fileURLToPath(import.meta.url))\nconst CATALOG_BASE_URL = 'https://cascivo.com'\n\nexport async function loadTokenCatalog(fetchFn?: FetchFn): Promise<TokenCatalog> {\n const localPaths = [\n join(HERE, '..', '..', '..', 'apps', 'docs', 'public', 'tokens.catalog.json'),\n join(HERE, 'tokens.catalog.json'),\n ]\n for (const p of localPaths) {\n if (existsSync(p)) return JSON.parse(readFileSync(p, 'utf8')) as TokenCatalog\n }\n const url = `${CATALOG_BASE_URL}/tokens.catalog.json`\n const fn = fetchFn ?? fetch\n const res = await fn(url)\n if (!res.ok) throw new Error(`Failed to fetch token catalog: ${res.status}`)\n return res.json() as Promise<TokenCatalog>\n}\n","import { existsSync, readFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nexport interface VariantToken {\n name: string\n layer: 'primitive' | 'semantic' | 'component'\n group: string\n role?: string\n slot?: string\n byTheme: Record<string, string | null>\n}\n\nexport interface VariantMatrix {\n generatedAt: string\n themes: string[]\n families: Record<string, Record<string, string>>\n tokens: VariantToken[]\n}\n\ntype FetchFn = (url: string, init?: RequestInit) => Promise<Response>\n\nconst HERE = dirname(fileURLToPath(import.meta.url))\nconst BASE_URL = 'https://cascivo.com'\n\nexport async function loadVariantMatrix(fetchFn?: FetchFn): Promise<VariantMatrix> {\n const localPaths = [\n join(HERE, '..', '..', '..', 'apps', 'docs', 'public', 'tokens.variants.json'),\n join(HERE, 'tokens.variants.json'),\n ]\n for (const p of localPaths) {\n if (existsSync(p)) return JSON.parse(readFileSync(p, 'utf8')) as VariantMatrix\n }\n const url = `${BASE_URL}/tokens.variants.json`\n const fn = fetchFn ?? fetch\n const res = await fn(url)\n if (!res.ok) throw new Error(`Failed to fetch variant matrix: ${res.status}`)\n return res.json() as Promise<VariantMatrix>\n}\n","/**\n * Shadow-sandbox component validator.\n *\n * Runs cascivo's own structural invariants over a candidate component's source\n * (TSX + CSS) *before* it is written to disk, so an agent can loop until the\n * source passes instead of emitting code that the repo's gates would later\n * reject. This is a static structural evaluation — not a full browser render —\n * but it catches the mistakes LLMs actually make against this design system:\n * banned React hooks, off-scale breakpoint literals, missing static fallbacks\n * for progressive CSS, and hallucinated `--cascivo-*` tokens.\n *\n * The checks mirror the repo gates:\n * - use-signals-gate / authoring rules → banned hooks\n * - breakpoint:check → off-scale @media/@container widths\n * - fallback:check → @function/if() static-fallback contract\n * - token catalog (closed set) → no hallucinated tokens\n */\n\nexport type Severity = 'error' | 'warning'\n\nexport interface ComponentViolation {\n rule: string\n severity: Severity\n line: number\n detail: string\n}\n\nexport interface ValidateComponentInput {\n /** Component TSX source. */\n tsx?: string\n /** Component CSS (module or plain) source. */\n css?: string\n /** Component name, for messages only. */\n name?: string\n}\n\nexport interface ValidateComponentOptions {\n /**\n * The closed set of valid `--cascivo-*` token names. When provided, any\n * `var(--cascivo-…)` reference outside this set is flagged as hallucinated.\n */\n tokenNames?: ReadonlySet<string>\n}\n\nexport interface ValidateComponentResult {\n valid: boolean\n name?: string\n violations: ComponentViolation[]\n}\n\n// Hooks that cascivo components must never use — signals replace them.\nconst BANNED_HOOKS = ['useState', 'useEffect', 'useLayoutEffect', 'useContext', 'useReducer']\n\n// Canonical breakpoint width literals (the only ones allowed in @media/@container).\nconst CANONICAL_WIDTHS = new Set([\n '30rem',\n '40rem',\n '64rem',\n '80rem',\n '480px',\n '640px',\n '1024px',\n '1280px',\n])\n\nfunction lineOf(source: string, index: number): number {\n let line = 1\n for (let i = 0; i < index && i < source.length; i++) {\n if (source[i] === '\\n') line++\n }\n return line\n}\n\n/** Detect banned React hooks in TSX (usage or import). */\nfunction checkBannedHooks(tsx: string): ComponentViolation[] {\n const violations: ComponentViolation[] = []\n for (const hook of BANNED_HOOKS) {\n const re = new RegExp(`\\\\b${hook}\\\\b`, 'g')\n let m: RegExpExecArray | null\n while ((m = re.exec(tsx)) !== null) {\n violations.push({\n rule: 'banned-hook',\n severity: 'error',\n line: lineOf(tsx, m.index),\n detail:\n hook === 'useEffect'\n ? `${hook} is banned — use useSignalEffect for DOM side effects`\n : `${hook} is banned — use useSignal/useComputed from @cascivo/core`,\n })\n }\n }\n return violations\n}\n\n/** Detect off-scale width literals in @media / @container conditions. */\nfunction checkBreakpoints(css: string): ComponentViolation[] {\n const violations: ComponentViolation[] = []\n const widthCondRe =\n /(?:min-width|max-width|width|min-inline-size|max-inline-size|inline-size)\\s*:\\s*([\\d.]+(?:rem|px|em))/g\n const lines = css.split('\\n')\n for (let i = 0; i < lines.length; i++) {\n const trimmed = (lines[i] ?? '').trim()\n if (!trimmed.startsWith('@media') && !trimmed.startsWith('@container')) continue\n if (\n /prefers|forced|pointer|hover|aspect|color|resolution|orientation|print|screen/.test(trimmed)\n )\n continue\n let m: RegExpExecArray | null\n widthCondRe.lastIndex = 0\n while ((m = widthCondRe.exec(trimmed)) !== null) {\n const value = m[1] ?? ''\n if (!CANONICAL_WIDTHS.has(value)) {\n violations.push({\n rule: 'off-scale-breakpoint',\n severity: 'error',\n line: i + 1,\n detail: `Off-scale width \"${value}\" — use 30rem/40rem/64rem/80rem`,\n })\n }\n }\n }\n return violations\n}\n\nconst isFunctionCall = (value: string) => /--[\\w-]+\\(/.test(value)\nconst isIfExpression = (value: string) => /\\bif\\s*\\(/.test(value)\n\n/** Enforce the @function / if() static-fallback contract. */\nfunction checkFallbacks(css: string): ComponentViolation[] {\n const violations: ComponentViolation[] = []\n const lines = css.split('\\n')\n let inSupports = false\n let supportsDepth = 0\n let baseSupportsDepth = 0\n interface Block {\n properties: Map<string, boolean>\n }\n const stack: Block[] = []\n\n for (let i = 0; i < lines.length; i++) {\n const line = (lines[i] ?? '').trim()\n if (/^@supports\\b/.test(line)) {\n inSupports = true\n baseSupportsDepth = supportsDepth\n }\n const opens = (line.match(/\\{/g) ?? []).length\n const closes = (line.match(/\\}/g) ?? []).length\n for (let j = 0; j < opens; j++) {\n stack.push({ properties: new Map() })\n supportsDepth++\n }\n for (let j = 0; j < closes; j++) {\n if (stack.length > 0) stack.pop()\n supportsDepth--\n if (supportsDepth <= baseSupportsDepth) inSupports = false\n }\n const declMatch = line.match(/^([\\w-]+)\\s*:\\s*(.+?)\\s*;?\\s*$/)\n if (!declMatch) continue\n const property = declMatch[1]!\n const value = declMatch[2]!\n if (isFunctionCall(value) || isIfExpression(value)) {\n let hasFallback = inSupports\n if (!hasFallback) {\n for (const block of stack) {\n if (block.properties.get(property)) {\n hasFallback = true\n break\n }\n }\n }\n if (!hasFallback) {\n violations.push({\n rule: 'missing-css-fallback',\n severity: 'error',\n line: i + 1,\n detail: `\"${property}\" uses @function/if() with no preceding static fallback`,\n })\n }\n } else if (stack.length > 0) {\n stack[stack.length - 1]!.properties.set(property, true)\n }\n }\n return violations\n}\n\n/** Flag `var(--cascivo-…)` references that are not in the closed token set. */\nfunction checkTokens(css: string, tokenNames: ReadonlySet<string>): ComponentViolation[] {\n if (tokenNames.size === 0) return []\n const violations: ComponentViolation[] = []\n const re = /var\\(\\s*(--cascivo-[\\w-]+)/g\n let m: RegExpExecArray | null\n const seen = new Set<string>()\n while ((m = re.exec(css)) !== null) {\n const token = m[1]!\n if (tokenNames.has(token) || seen.has(token)) continue\n seen.add(token)\n violations.push({\n rule: 'unknown-token',\n severity: 'error',\n line: lineOf(css, m.index),\n detail: `\"${token}\" is not in the cascivo token catalog (hallucinated token)`,\n })\n }\n return violations\n}\n\n/** Run all structural invariants over a candidate component's source. */\nexport function validateComponentSource(\n input: ValidateComponentInput,\n options: ValidateComponentOptions = {},\n): ValidateComponentResult {\n const violations: ComponentViolation[] = []\n if (input.tsx) violations.push(...checkBannedHooks(input.tsx))\n if (input.css) {\n violations.push(...checkBreakpoints(input.css))\n violations.push(...checkFallbacks(input.css))\n if (options.tokenNames) violations.push(...checkTokens(input.css, options.tokenNames))\n }\n violations.sort((a, b) => a.line - b.line)\n return {\n valid: violations.every((v) => v.severity !== 'error'),\n ...(input.name ? { name: input.name } : {}),\n violations,\n }\n}\n","import { existsSync, readFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nexport interface ContextRelated {\n name: string\n relationship: string\n reason: string\n}\n\nexport interface ContextAntiPattern {\n bad: string\n good: string\n why: string\n}\n\nexport interface ContextFlexibility {\n area: string\n level: string\n note: string\n}\n\nexport interface ComponentIntent {\n whenToUse: string[]\n whenNotToUse: string[]\n antiPatterns: ContextAntiPattern[]\n related: ContextRelated[]\n a11yRationale?: string\n flexibility?: ContextFlexibility[]\n}\n\nexport interface ContextComponent {\n name: string\n category: string\n description: string\n intent: ComponentIntent\n contextUrl: string\n /** Copy-pasteable system-prompt snippet that pins an LLM to this component. */\n aiPrompt?: string\n}\n\nexport interface ContextBundle {\n generatedAt: string\n tagline: string\n authoringRules: string[]\n tokenCatalogUrl: string\n components: ContextComponent[]\n}\n\ntype FetchFn = (url: string, init?: RequestInit) => Promise<Response>\n\nconst HERE = dirname(fileURLToPath(import.meta.url))\nconst CONTEXT_BASE_URL = 'https://cascivo.com'\n\nexport async function loadContext(fetchFn?: FetchFn): Promise<ContextBundle> {\n const localPaths = [\n join(HERE, '..', '..', '..', 'apps', 'docs', 'public', 'context.json'),\n join(HERE, 'context.json'),\n ]\n for (const p of localPaths) {\n if (existsSync(p)) return JSON.parse(readFileSync(p, 'utf8')) as ContextBundle\n }\n const url = `${CONTEXT_BASE_URL}/context.json`\n const fn = fetchFn ?? fetch\n const res = await fn(url)\n if (!res.ok) throw new Error(`Failed to fetch context bundle: ${res.status}`)\n return res.json() as Promise<ContextBundle>\n}\n\nexport async function loadComponentMarkdown(\n name: string,\n fetchFn?: FetchFn,\n): Promise<string | null> {\n const slug = name.toLowerCase().replace(/\\s+/g, '-')\n const localPaths = [\n join(HERE, '..', '..', '..', 'apps', 'docs', 'public', 'context', `${slug}.md`),\n join(HERE, 'context', `${slug}.md`),\n ]\n for (const p of localPaths) {\n if (existsSync(p)) return readFileSync(p, 'utf8')\n }\n const url = `${CONTEXT_BASE_URL}/context/${slug}.md`\n const fn = fetchFn ?? fetch\n try {\n const res = await fn(url)\n if (!res.ok) return null\n return res.text()\n } catch {\n return null\n }\n}\n","import type { ContextComponent } from './context.js'\n\nexport interface SelectRelated {\n name: string\n relationship: string\n reason: string\n}\n\nexport interface SelectResult {\n name: string\n score: number\n why: string\n /** When NOT to use this pick — lets an agent disqualify a wrong match. */\n whenNotToUse: string[]\n /** Related components (alternatives, pairs-with) to consider instead/alongside. */\n related: SelectRelated[]\n}\n\n// Minimum length for a need word to be scored (filters out articles, prepositions, etc.)\nconst MIN_WORD_LEN = 3\n\nfunction words(text: string): string[] {\n return (text.toLowerCase().match(/\\b\\w+\\b/g) ?? []).filter((w) => w.length >= MIN_WORD_LEN)\n}\n\nfunction countMatches(needWords: string[], text: string): string[] {\n const lower = text.toLowerCase()\n return needWords.filter((w) => lower.includes(w))\n}\n\nexport function selectComponent(need: string, components: ContextComponent[]): SelectResult[] {\n const needWords = words(need)\n if (needWords.length === 0) return []\n\n const scored = components.map((c) => {\n const whenToUseText = c.intent.whenToUse.join(' ')\n const whenNotToUseText = c.intent.whenNotToUse.join(' ')\n\n const whenToUseMatches = countMatches(needWords, whenToUseText)\n const descMatches = countMatches(needWords, c.description)\n const penaltyMatches = countMatches(needWords, whenNotToUseText)\n\n const score = whenToUseMatches.length * 2 + descMatches.length - penaltyMatches.length * 3\n\n // Build why from the best-matching whenToUse sentence\n let why = ''\n if (whenToUseMatches.length > 0) {\n const bestSentence = c.intent.whenToUse\n .map((s) => ({ s, count: countMatches(needWords, s).length }))\n .filter((x) => x.count > 0)\n .sort((a, b) => b.count - a.count)[0]?.s\n why = bestSentence\n ? `Matched: ${whenToUseMatches.map((w) => `'${w}'`).join(', ')} in whenToUse — \"${bestSentence}\"`\n : `Matched: ${whenToUseMatches.map((w) => `'${w}'`).join(', ')} in description`\n } else if (descMatches.length > 0) {\n why = `Matched: ${descMatches.map((w) => `'${w}'`).join(', ')} in description`\n }\n\n return {\n name: c.name,\n score,\n why,\n whenNotToUse: c.intent.whenNotToUse ?? [],\n related: c.intent.related ?? [],\n }\n })\n\n // First pass: top 3 by score for related bonus\n const top3Names = new Set(\n [...scored]\n .sort((a, b) => b.score - a.score || a.name.localeCompare(b.name))\n .slice(0, 3)\n .map((r) => r.name),\n )\n\n // Apply related bonus: +1 if a top-3 component points at this component\n const relatedBonus = new Map<string, number>()\n for (const r of scored) {\n if (!top3Names.has(r.name)) continue\n for (const rel of r.related) {\n relatedBonus.set(rel.name, (relatedBonus.get(rel.name) ?? 0) + 1)\n }\n }\n\n const final = scored.map((r) => ({\n name: r.name,\n score: r.score + (relatedBonus.get(r.name) ?? 0),\n why: r.why,\n whenNotToUse: r.whenNotToUse,\n related: r.related,\n }))\n\n return final\n .filter((r) => r.score >= 0)\n .sort((a, b) => b.score - a.score || a.name.localeCompare(b.name))\n .slice(0, 5)\n}\n","import { spawnSync } from 'node:child_process'\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { z } from 'zod'\nimport {\n fetchDirectory,\n fetchRegistryIndex,\n getComponent,\n getEnvRegistries,\n listComponents,\n loadRegistry,\n mergeRegistries,\n searchComponents,\n type Registry,\n} from './registry.js'\nimport { generateThemeCss } from './theme.js'\nimport { scaffoldPage } from './scaffold.js'\nimport { validateView } from './validate.js'\nimport { scaffoldView } from './scaffold-view.js'\nimport { buildGrammar, formatGrammar } from './grammar.js'\nimport { buildGenerationPrompt } from './prompt.js'\nimport { loadTokenCatalog } from './tokens.js'\nimport { loadVariantMatrix } from './variants.js'\nimport { validateComponentSource } from './validate-component.js'\nimport { loadContext, loadComponentMarkdown } from './context.js'\nimport { selectComponent } from './select.js'\n\ntype FetchFn = (url: string, init?: RequestInit) => Promise<Response>\n\nexport interface ServerOptions {\n registryPath?: string\n version?: string\n /** Injectable fetch function — used for testing multi-registry features. */\n fetchFn?: FetchFn\n}\n\nconst json = (value: unknown) => ({\n content: [{ type: 'text' as const, text: JSON.stringify(value, null, 2) }],\n})\n\nconst text = (value: string) => ({ content: [{ type: 'text' as const, text: value }] })\n\nconst error = (message: string) => ({\n content: [{ type: 'text' as const, text: message }],\n isError: true,\n})\n\n/** Build a configured McpServer exposing the cascade component registry. */\nexport function createServer(options: ServerOptions = {}): McpServer {\n const registry: Registry = loadRegistry(options.registryPath)\n const fetchFn = options.fetchFn\n\n const server = new McpServer({\n name: '@cascivo/mcp',\n version: options.version ?? '0.0.0',\n })\n\n server.registerTool(\n 'list_registries',\n {\n title: 'List registries',\n description:\n 'List available component registries: the cascade directory plus any configured via CASCADE_REGISTRIES env.',\n inputSchema: {},\n },\n async () => {\n const directory = await fetchDirectory(fetchFn)\n const env = getEnvRegistries()\n const entries = mergeRegistries(directory, env)\n return json(\n entries.map(({ namespace, name, description, verified, homepage }) => ({\n namespace,\n name,\n description,\n verified: verified ?? false,\n homepage,\n })),\n )\n },\n )\n\n server.registerTool(\n 'list_components',\n {\n title: 'List components',\n description: 'List all cascade components, optionally filtered by category and/or type.',\n inputSchema: {\n category: z\n .enum(['inputs', 'display', 'overlay', 'navigation', 'feedback', 'chart'])\n .optional()\n .describe('Filter by component category'),\n type: z\n .enum(['component', 'layout', 'block', 'chart', 'flow'])\n .optional()\n .describe('Filter by entry type'),\n },\n },\n ({ category, type }) => json(listComponents(registry, category, type)),\n )\n\n server.registerTool(\n 'get_component',\n {\n title: 'Get component',\n description:\n 'Get the full manifest (props, states, tokens, a11y, examples) for one component.',\n inputSchema: {\n name: z.string().describe('Component name, e.g. \"button\"'),\n registry: z\n .string()\n .optional()\n .describe('Namespace of an external registry, e.g. \"@myns\". Omit for the default.'),\n },\n },\n async ({ name, registry: ns }) => {\n if (ns) {\n const env = getEnvRegistries()\n const directory = await fetchDirectory(fetchFn)\n const entries = mergeRegistries(directory, env)\n const entry = entries.find((e) => e.namespace === ns)\n if (!entry) return error(`Registry \"${ns}\" not found.`)\n const remoteRegistry = await fetchRegistryIndex(entry.registryUrl, fetchFn)\n if (!remoteRegistry) return error(`Failed to fetch registry index for \"${ns}\".`)\n const meta = getComponent(remoteRegistry, name)\n return meta ? json(meta) : error(`Component \"${name}\" not found in registry \"${ns}\".`)\n }\n const meta = getComponent(registry, name)\n return meta ? json(meta) : error(`Component \"${name}\" not found.`)\n },\n )\n\n server.registerTool(\n 'search_components',\n {\n title: 'Search components',\n description: 'Fuzzy search components by name, tags, or description.',\n inputSchema: {\n query: z.string().describe('Search query'),\n registry: z\n .string()\n .optional()\n .describe('Namespace of an external registry, e.g. \"@myns\". Omit for the default.'),\n },\n },\n async ({ query, registry: ns }) => {\n if (ns) {\n const env = getEnvRegistries()\n const directory = await fetchDirectory(fetchFn)\n const entries = mergeRegistries(directory, env)\n const entry = entries.find((e) => e.namespace === ns)\n if (!entry) return error(`Registry \"${ns}\" not found.`)\n const remoteRegistry = await fetchRegistryIndex(entry.registryUrl, fetchFn)\n if (!remoteRegistry) return error(`Failed to fetch registry index for \"${ns}\".`)\n return json(searchComponents(remoteRegistry, query))\n }\n return json(searchComponents(registry, query))\n },\n )\n\n server.registerTool(\n 'add_to_project',\n {\n title: 'Add to project',\n description: 'Add a component to the current project by running the cascade CLI.',\n inputSchema: {\n name: z.string().describe('Component name to add'),\n outputDir: z.string().optional().describe('Directory to write the component into'),\n },\n },\n ({ name, outputDir }) => {\n const env = outputDir ? { ...process.env, CASCIVO_OUTPUT_DIR: outputDir } : process.env\n const result = spawnSync('npx', ['-y', 'cascivo', 'add', name], { encoding: 'utf8', env })\n if (result.status !== 0) {\n return error(result.stderr || result.error?.message || `Failed to add \"${name}\".`)\n }\n return text(result.stdout || `Added ${name}.`)\n },\n )\n\n server.registerTool(\n 'create_theme',\n {\n title: 'Create theme',\n description: 'Generate a cascade theme CSS file from three colors.',\n inputSchema: {\n primary: z.string().describe('Primary / interactive color (any CSS color)'),\n neutral: z.string().describe('Base neutral color for surfaces and text'),\n accent: z.string().describe('Secondary accent color (info / focus)'),\n name: z.string().optional().describe('Theme name (default: \"custom\")'),\n },\n },\n ({ primary, neutral, accent, name }) =>\n text(generateThemeCss({ primary, neutral, accent }, name)),\n )\n\n server.registerTool(\n 'scaffold_page',\n {\n title: 'Scaffold page (deprecated)',\n description:\n '[Deprecated — use scaffold_view instead] Generate a JSX page layout from a description.',\n inputSchema: {\n description: z.string().describe('What the page is for'),\n components: z.array(z.string()).optional().describe('Components to include'),\n },\n },\n ({ description, components }) => {\n const { config } = scaffoldView(\n { description, ...(components ? { components } : {}) },\n registry,\n )\n return text(\n `[Deprecated] Use scaffold_view for config-first output. JSX scaffold:\\n\\n${scaffoldPage(components ? { description, components } : { description })}\\n\\n--- scaffold_view output ---\\n${JSON.stringify(config, null, 2)}`,\n )\n },\n )\n\n server.registerTool(\n 'validate_view',\n {\n title: 'Validate view config',\n description:\n 'Validate a CascadeView JSON config against the registry. Returns errors with exact paths.',\n inputSchema: {\n config: z.record(z.string(), z.unknown()).describe('The ViewConfig object to validate'),\n },\n },\n ({ config }) => {\n const componentNames = new Set(registry.components.map((c) => c.meta.name))\n const result = validateView(config, componentNames)\n return json(result)\n },\n )\n\n server.registerTool(\n 'scaffold_view',\n {\n title: 'Scaffold view config',\n description:\n 'Generate a valid starter ViewConfig from a description. Always validates before returning.',\n inputSchema: {\n description: z.string().describe('What the page/view is for'),\n components: z.array(z.string()).optional().describe('Component names to include'),\n },\n },\n ({ description, components }) => {\n const { config, errors, grammar } = scaffoldView(\n { description, ...(components ? { components } : {}) },\n registry,\n )\n if (errors.length > 0) {\n return json({ valid: false, errors, config, grammar })\n }\n return json({ valid: true, config, grammar })\n },\n )\n\n server.registerTool(\n 'scaffold_flow',\n {\n title: 'Scaffold a flow diagram',\n description:\n 'Generate a starter declarative <Flow nodes edges /> (from @cascivo/flow) for a node/edge diagram — flowchart, DAG, or pipeline. Returns serializable nodes/edges plus ready-to-paste JSX. Edit the labels/edges to match the intent.',\n inputSchema: {\n description: z.string().describe('What the diagram represents'),\n steps: z\n .array(z.string())\n .optional()\n .describe(\n 'Ordered step labels; consecutive steps are connected. Omit for a 3-step starter.',\n ),\n layout: z\n .enum(['none', 'grid', 'layered'])\n .optional()\n .describe('Optional auto-layout. Default \"layered\".'),\n },\n },\n ({ description, steps, layout }) => {\n const labels = steps && steps.length > 0 ? steps : ['Source', 'Process', 'Sink']\n const nodes = labels.map((label, i) => ({\n id: `n${i + 1}`,\n position: { x: i * 240, y: 0 },\n data: { label },\n }))\n const edges = labels.slice(1).map((_, i) => ({\n id: `e${i + 1}`,\n source: `n${i + 1}`,\n target: `n${i + 2}`,\n animated: true,\n }))\n const lay = layout ?? 'layered'\n const layoutProp = lay === 'none' ? '' : ` layout=\"${lay}\"`\n const code = `import { Flow } from '@cascivo/flow'\nimport '@cascivo/flow/styles.css'\n\n// ${description}\nexport function Diagram() {\n return (\n <Flow\n style={{ height: 360 }}\n background\n controls${layoutProp}\n nodes={${JSON.stringify(nodes)}}\n edges={${JSON.stringify(edges)}}\n />\n )\n}`\n return json({ nodes, edges, layout: lay, code })\n },\n )\n\n server.registerTool(\n 'get_view_grammar',\n {\n title: 'Get view grammar',\n description:\n \"Get the bound-vocabulary grammar + system prompt for generating valid ViewConfig JSON, derived from the component manifests. Use this to constrain an LLM to cascivo's real components, props, and enum values (anti-hallucination). Optionally scope to a subset of components.\",\n inputSchema: {\n components: z\n .array(z.string())\n .optional()\n .describe('Scope the vocabulary to these component names. Omit for the full registry.'),\n },\n },\n ({ components }) => {\n const grammar = buildGrammar(registry, components)\n return json({\n grammar: formatGrammar(grammar),\n prompt: buildGenerationPrompt(registry, components ? { components } : {}),\n components: grammar.components,\n })\n },\n )\n\n server.registerTool(\n 'get_tokens',\n {\n title: 'Get tokens',\n description:\n 'Get the cascade token catalog (closed set). Agents must select from this catalog rather than hard-coding values.',\n inputSchema: {\n group: z\n .string()\n .optional()\n .describe('Filter by token group, e.g. \"color\", \"space\", \"radius\"'),\n layer: z\n .enum(['primitive', 'semantic', 'component'])\n .optional()\n .describe('Filter by layer'),\n },\n },\n async ({ group, layer }) => {\n try {\n const catalog = await loadTokenCatalog(fetchFn)\n let tokens = catalog.tokens\n if (group) tokens = tokens.filter((t) => t.group === group)\n if (layer) tokens = tokens.filter((t) => t.layer === layer)\n return json({ count: tokens.length, tokens })\n } catch (e) {\n return error(`Token catalog unavailable: ${e instanceof Error ? e.message : String(e)}`)\n }\n },\n )\n\n server.registerTool(\n 'get_variant_matrix',\n {\n title: 'Get variant matrix',\n description:\n 'Get the deterministic token variant matrix: a map from design intent (a colour role + state slot, e.g. accent + hover) to the exact token name, plus every semantic/component token resolved to a concrete value in each theme. Use this to answer \"what is the warm theme\\'s accent-hover value?\" or \"which token is the active state of primary?\" without guessing how layered theme CSS resolves.',\n inputSchema: {\n role: z\n .string()\n .optional()\n .describe('Filter to one colour role, e.g. \"accent\", \"primary\", \"destructive\"'),\n theme: z\n .string()\n .optional()\n .describe('Restrict the per-theme values to a single theme, e.g. \"warm\"'),\n },\n },\n async ({ role, theme }) => {\n try {\n const matrix = await loadVariantMatrix(fetchFn)\n if (theme && !matrix.themes.includes(theme)) {\n return error(`Unknown theme \"${theme}\". Available: ${matrix.themes.join(', ')}`)\n }\n const pickTheme = (byTheme: Record<string, string | null>) =>\n theme ? { [theme]: byTheme[theme] ?? null } : byTheme\n let tokens = matrix.tokens\n let families = matrix.families\n if (role) {\n tokens = tokens.filter((t) => t.role === role)\n families = matrix.families[role] ? { [role]: matrix.families[role] } : {}\n if (tokens.length === 0) {\n const available = Object.keys(matrix.families).join(', ')\n return error(`No colour role \"${role}\". Available roles: ${available}`)\n }\n }\n return json({\n themes: theme ? [theme] : matrix.themes,\n families,\n tokens: tokens.map((t) => ({ ...t, byTheme: pickTheme(t.byTheme) })),\n })\n } catch (e) {\n return error(`Variant matrix unavailable: ${e instanceof Error ? e.message : String(e)}`)\n }\n },\n )\n\n server.registerTool(\n 'validate_component',\n {\n title: 'Validate component (shadow sandbox)',\n description:\n \"Run cascivo's structural invariants over candidate component source (TSX and/or CSS) before writing it to disk. Catches banned React hooks, off-scale @media/@container breakpoints, missing static fallbacks for progressive CSS (@function/if()), and hallucinated --cascivo-* tokens. Use this to self-correct generated code in a loop until `valid` is true.\",\n inputSchema: {\n tsx: z.string().optional().describe('Component TSX source'),\n css: z.string().optional().describe('Component CSS (module or plain) source'),\n name: z.string().optional().describe('Component name (for messages only)'),\n },\n },\n async ({ tsx, css, name }) => {\n let tokenNames: Set<string> | undefined\n try {\n const catalog = await loadTokenCatalog(fetchFn)\n tokenNames = new Set(catalog.tokens.map((t) => t.name))\n } catch {\n // Token catalog is optional — skip the hallucination check if unavailable.\n }\n const result = validateComponentSource(\n { ...(tsx ? { tsx } : {}), ...(css ? { css } : {}), ...(name ? { name } : {}) },\n tokenNames ? { tokenNames } : {},\n )\n return json(result)\n },\n )\n\n server.registerTool(\n 'get_context',\n {\n title: 'Get context',\n description:\n 'Get intent, whenToUse/whenNotToUse, and authoring guidance for one component by name.',\n inputSchema: {\n name: z.string().describe('Component name, e.g. \"Toast\"'),\n },\n },\n async ({ name }) => {\n try {\n const ctx = await loadContext(fetchFn)\n const target = name.toLowerCase()\n const component = ctx.components.find((c) => c.name.toLowerCase() === target)\n if (!component) {\n const available = ctx.components.map((c) => c.name).join(', ')\n return error(`Component \"${name}\" not found. Available: ${available}`)\n }\n const md = await loadComponentMarkdown(component.name, fetchFn)\n return json({\n name: component.name,\n category: component.category,\n description: component.description,\n intent: component.intent,\n contextUrl: component.contextUrl,\n ...(component.aiPrompt ? { aiPrompt: component.aiPrompt } : {}),\n ...(md ? { markdown: md } : {}),\n })\n } catch (e) {\n return error(`Context bundle unavailable: ${e instanceof Error ? e.message : String(e)}`)\n }\n },\n )\n\n server.registerTool(\n 'select_component',\n {\n title: 'Select component',\n description:\n 'Heuristic ranking of cascade components by natural language need. Returns top matches with scores and reasons. Note: heuristic ranking, not a model call.',\n inputSchema: {\n need: z.string().describe('Natural language description of what the component should do'),\n },\n },\n async ({ need }) => {\n try {\n const ctx = await loadContext(fetchFn)\n const results = selectComponent(need, ctx.components)\n return json({\n note: 'Heuristic ranking — not a model call. Verify with get_context before using.',\n results,\n })\n } catch (e) {\n return error(`Context bundle unavailable: ${e instanceof Error ? e.message : String(e)}`)\n }\n },\n )\n\n return server\n}\n","import { argv } from 'node:process'\nimport { pathToFileURL } from 'node:url'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { createServer } from './server.js'\n\nexport const VERSION = '0.0.0'\n\nexport { createServer } from './server.js'\nexport type { ServerOptions } from './server.js'\nexport { generateThemeCss, type ThemeColors } from './theme.js'\nexport { scaffoldPage, type ScaffoldOptions } from './scaffold.js'\nexport {\n buildGrammar,\n formatGrammar,\n parseEnum,\n type GrammarComponent,\n type GrammarProp,\n type ViewGrammar,\n} from './grammar.js'\nexport { buildGenerationPrompt, type GenerationPromptOptions } from './prompt.js'\nexport {\n getComponent,\n listComponents,\n loadRegistry,\n searchComponents,\n type ComponentManifest,\n type Registry,\n type RegistryComponent,\n} from './registry.js'\n\n/** Start the MCP server over stdio. */\nexport async function main(): Promise<void> {\n const server = createServer({ version: VERSION })\n await server.connect(new StdioServerTransport())\n}\n\nconst isMain = argv[1] !== undefined && import.meta.url === pathToFileURL(argv[1]).href\n\nif (isMain) {\n main().catch((err: unknown) => {\n console.error(err instanceof Error ? err.message : String(err))\n process.exitCode = 1\n })\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["HERE","c","v","HERE","HERE"],"sources":["../src/registry.ts","../src/theme.ts","../src/scaffold.ts","../src/validate.ts","../src/grammar.ts","../src/scaffold-view.ts","../src/prompt.ts","../src/tokens.ts","../src/variants.ts","../src/validate-component.ts","../src/context.ts","../src/select.ts","../src/server.ts","../src/index.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nexport interface PropManifest {\n name: string\n type: string\n required: boolean\n default?: string\n description?: string\n}\n\nexport interface ComponentManifest {\n name: string\n description: string\n category: string\n states: string[]\n variants: string[]\n sizes: string[]\n props: PropManifest[]\n tokens: string[]\n accessibility: { role: string; wcag: string; keyboard: string[] }\n examples: { title: string; code: string; description?: string }[]\n dependencies: string[]\n tags: string[]\n}\n\nexport interface RegistryComponent {\n name: string\n type?: 'component' | 'layout' | 'block' | 'chart' | 'section' | 'flow'\n description: string\n category: string\n version: string\n files: string[]\n dependencies: string[]\n tags: string[]\n meta: ComponentManifest\n}\n\nexport interface Registry {\n version: string\n generatedAt: string\n components: RegistryComponent[]\n}\n\nconst HERE = dirname(fileURLToPath(import.meta.url))\n\n/**\n * Resolve the registry.json location. Checks, in order: an explicit path, the\n * `CASCIVO_REGISTRY_PATH` env var, a copy bundled next to the built server\n * (published package), and the monorepo root (dev).\n */\nexport function resolveRegistryPath(explicit?: string): string {\n const candidates = [\n explicit,\n process.env.CASCIVO_REGISTRY_PATH,\n join(HERE, 'registry.json'),\n join(HERE, '..', '..', '..', 'registry.json'),\n join(HERE, '..', '..', 'registry.json'),\n ].filter((p): p is string => typeof p === 'string' && p.length > 0)\n\n return (\n candidates.find((p) => existsSync(p)) ?? candidates[candidates.length - 1] ?? 'registry.json'\n )\n}\n\nexport function loadRegistry(path?: string): Registry {\n const resolved = resolveRegistryPath(path)\n const raw = JSON.parse(readFileSync(resolved, 'utf8')) as Registry\n if (!Array.isArray(raw.components)) {\n throw new Error(`Invalid registry at ${resolved}: \"components\" must be an array`)\n }\n return raw\n}\n\n/** List component manifests, optionally filtered by category and/or type. */\nexport function listComponents(\n registry: Registry,\n category?: string,\n type?: string,\n): ComponentManifest[] {\n let entries = registry.components\n if (category) entries = entries.filter((c) => c.category === category)\n if (type) entries = entries.filter((c) => c.type === type)\n return entries.map((c) => c.meta)\n}\n\n/** Find one component manifest by name (matches registry name or meta name). */\nexport function getComponent(registry: Registry, name: string): ComponentManifest | undefined {\n const target = name.toLowerCase()\n return registry.components.find(\n (c) => c.name.toLowerCase() === target || c.meta.name.toLowerCase() === target,\n )?.meta\n}\n\n// ---------------------------------------------------------------------------\n// Multi-registry support\n// ---------------------------------------------------------------------------\n\nexport interface RegistryDirectoryEntry {\n namespace: string\n name: string\n description?: string\n registryUrl: string\n verified?: boolean\n homepage?: string\n}\n\nconst DIRECTORY_URL = 'https://cascivo.com/r/registries.json'\nconst FETCH_TIMEOUT_MS = 15_000\nconst MAX_BODY_BYTES = 1_048_576 // 1 MB\n\ntype FetchFn = (url: string, init?: RequestInit) => Promise<Response>\n\nasync function fetchWithGuards(url: string, fetchFn: FetchFn = fetch): Promise<string | null> {\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS)\n try {\n const res = await fetchFn(url, { signal: controller.signal })\n if (!res.ok) return null\n const buf = await res.arrayBuffer()\n if (buf.byteLength > MAX_BODY_BYTES) return null\n return new TextDecoder().decode(buf)\n } catch {\n return null\n } finally {\n clearTimeout(timer)\n }\n}\n\n/** Fetch the central cascade registry directory. Returns empty array on failure. */\nexport async function fetchDirectory(fetchFn?: FetchFn): Promise<RegistryDirectoryEntry[]> {\n const raw = await fetchWithGuards(DIRECTORY_URL, fetchFn)\n if (!raw) return []\n try {\n const parsed = JSON.parse(raw) as unknown\n if (!Array.isArray(parsed)) return []\n return parsed as RegistryDirectoryEntry[]\n } catch {\n return []\n }\n}\n\n/** Fetch the component index from a namespace's registryUrl. Returns null on failure. */\nexport async function fetchRegistryIndex(\n registryUrl: string,\n fetchFn?: FetchFn,\n): Promise<Registry | null> {\n // Resolve the registry.json URL: replace trailing `{name}` template or append /registry.json\n const indexUrl = registryUrl.includes('{name}')\n ? registryUrl.replace('{name}', 'registry').replace(/\\/registry$/, '/registry.json')\n : registryUrl.replace(/\\/?$/, '/registry.json').replace(/\\/\\/registry\\.json$/, '/registry.json')\n const raw = await fetchWithGuards(indexUrl, fetchFn)\n if (!raw) return null\n try {\n const parsed = JSON.parse(raw) as Registry\n if (!Array.isArray(parsed.components)) return null\n return parsed\n } catch {\n return null\n }\n}\n\n/** Parse CASCADE_REGISTRIES env var — returns empty array on failure. */\nexport function getEnvRegistries(): RegistryDirectoryEntry[] {\n const raw = process.env['CASCADE_REGISTRIES']\n if (!raw) return []\n try {\n const parsed = JSON.parse(raw) as unknown\n if (!Array.isArray(parsed)) return []\n return parsed as RegistryDirectoryEntry[]\n } catch {\n return []\n }\n}\n\n/** Merge directory entries with env entries (env wins on namespace collision). */\nexport function mergeRegistries(\n directory: RegistryDirectoryEntry[],\n env: RegistryDirectoryEntry[],\n): RegistryDirectoryEntry[] {\n const map = new Map<string, RegistryDirectoryEntry>()\n for (const entry of directory) map.set(entry.namespace, entry)\n for (const entry of env) map.set(entry.namespace, entry)\n return Array.from(map.values())\n}\n\n/** Fuzzy search over name, tags, and description. */\nexport function searchComponents(registry: Registry, query: string): ComponentManifest[] {\n const q = query.toLowerCase().trim()\n if (q === '') return []\n return registry.components\n .filter(\n (c) =>\n c.name.toLowerCase().includes(q) ||\n c.description.toLowerCase().includes(q) ||\n c.tags.some((t) => t.toLowerCase().includes(q)),\n )\n .map((c) => c.meta)\n}\n","export interface ThemeColors {\n /** Main brand / interactive color (maps to the accent token family). */\n primary: string\n /** Base gray used to derive surfaces, borders, and text. */\n neutral: string\n /** Secondary highlight color (info / focus ring). */\n accent: string\n}\n\n/** Darken a color by mixing in black (modern CSS, no preprocessor). */\nfunction darken(color: string, amount: number): string {\n return `color-mix(in oklab, ${color}, black ${amount}%)`\n}\n\n/** Lighten a color by mixing in white. */\nfunction lighten(color: string, amount: number): string {\n return `color-mix(in oklab, ${color}, white ${amount}%)`\n}\n\n/**\n * Generate a custom cascivo theme as CSS. Maps the three input colors onto the\n * semantic token layer; component tokens inherit automatically.\n */\nexport function generateThemeCss(colors: ThemeColors, name = 'custom'): string {\n const { primary, neutral, accent } = colors\n return `/* cascivo — Generated theme: ${name} */\n\n@layer cascivo.theme {\n [data-theme='${name}'] {\n color-scheme: light;\n\n /* ── Surface (derived from neutral) ───────────────── */\n --cascivo-color-bg: ${lighten(neutral, 96)};\n --cascivo-color-bg-subtle: ${lighten(neutral, 92)};\n --cascivo-color-surface: ${lighten(neutral, 98)};\n --cascivo-color-surface-raised: ${lighten(neutral, 94)};\n --cascivo-color-surface-overlay: ${lighten(neutral, 98)};\n --cascivo-color-border: ${lighten(neutral, 80)};\n --cascivo-color-border-strong: ${lighten(neutral, 65)};\n\n /* ── Text (derived from neutral) ──────────────────── */\n --cascivo-color-text: ${darken(neutral, 80)};\n --cascivo-color-text-subtle: ${darken(neutral, 50)};\n --cascivo-color-text-muted: ${lighten(neutral, 30)};\n --cascivo-color-text-on-accent: #ffffff;\n --cascivo-color-text-on-destructive: #ffffff;\n\n /* ── Accent / primary interactive ─────────────────── */\n --cascivo-color-accent: ${primary};\n --cascivo-color-accent-hover: ${darken(primary, 12)};\n --cascivo-color-accent-active: ${darken(primary, 24)};\n --cascivo-color-accent-subtle: ${lighten(primary, 88)};\n --cascivo-color-accent-muted: ${lighten(primary, 76)};\n\n /* ── Secondary accent (info / focus) ──────────────── */\n --cascivo-color-info: ${accent};\n --cascivo-color-info-subtle: ${lighten(accent, 88)};\n --cascivo-color-focus-ring: ${accent};\n --cascivo-focus-ring: 0 0 0 3px ${lighten(accent, 20)};\n\n /* ── Status ───────────────────────────────────────── */\n --cascivo-color-destructive: #dc2626;\n --cascivo-color-destructive-hover: ${darken('#dc2626', 12)};\n --cascivo-color-destructive-subtle: ${lighten('#dc2626', 88)};\n --cascivo-color-success: #16a34a;\n --cascivo-color-success-subtle: ${lighten('#16a34a', 88)};\n --cascivo-color-warning: #f59e0b;\n --cascivo-color-warning-subtle: ${lighten('#f59e0b', 88)};\n }\n}\n`\n}\n","export interface ScaffoldOptions {\n description: string\n components?: string[]\n}\n\nconst DEFAULT_COMPONENTS = ['card', 'input', 'button']\n\nfunction pascalCase(name: string): string {\n return name\n .split(/[-_\\s]+/)\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join('')\n}\n\n/** A reasonable default usage snippet per component for the scaffold. */\nfunction usage(component: string, Tag: string): string {\n switch (component) {\n case 'button':\n return ` <${Tag}>Get started</${Tag}>`\n case 'input':\n return ` <${Tag} label=\"Email\" placeholder=\"you@example.com\" />`\n case 'card':\n return ` <${Tag}>\\n <h2>Card title</h2>\\n <p>Card content goes here.</p>\\n </${Tag}>`\n case 'badge':\n return ` <${Tag}>New</${Tag}>`\n default:\n return ` <${Tag} />`\n }\n}\n\n/**\n * Generate a JSX page layout string from a natural-language description and an\n * optional list of cascade components to include.\n */\nexport function scaffoldPage(options: ScaffoldOptions): string {\n const components = options.components?.length ? options.components : DEFAULT_COMPONENTS\n const unique = [...new Set(components.map((c) => c.toLowerCase()))]\n\n const imports = unique\n .map((c) => `import { ${pascalCase(c)} } from './components/ui/${c}/${c}'`)\n .join('\\n')\n\n const body = unique.map((c) => usage(c, pascalCase(c))).join('\\n')\n\n return `${imports}\n\n/* ${options.description} */\nexport function Page() {\n return (\n <main\n data-theme=\"light\"\n style={{ maxWidth: '48rem', margin: '0 auto', padding: '2rem', display: 'grid', gap: '1rem' }}\n >\n${body}\n </main>\n )\n}\n`\n}\n","// Inlined from @cascivo/render — avoids a Node.js binary depending on React components at runtime.\n// Component name validation uses the registry (passed by caller) instead of the React component map.\n\nexport interface ValidationError {\n path: string\n message: string\n}\n\nexport interface ComponentNode {\n component: string\n props?: Record<string, unknown>\n bind?: Record<string, string>\n events?: Record<string, string>\n children?: ComponentNode[] | string\n}\n\nexport interface ViewConfig {\n $schema?: string\n version?: 1\n view: {\n layout?: string\n regions: Record<string, ComponentNode[]>\n }\n}\n\nconst DATA_REF_RE = /^\\$data\\./\nconst ACTION_REF_RE = /^\\$actions\\./\n\nfunction closestName(name: string, candidates: string[]): string | undefined {\n const target = name.toLowerCase()\n let best: string | undefined\n let bestDist = 3\n for (const candidate of candidates) {\n const dist = levenshtein(target, candidate.toLowerCase())\n if (dist < bestDist) {\n bestDist = dist\n best = candidate\n }\n }\n return best\n}\n\nfunction levenshtein(a: string, b: string): number {\n const m = a.length\n const n = b.length\n const dp: number[][] = Array.from({ length: m + 1 }, (_, i) =>\n Array.from({ length: n + 1 }, (_, j) => (i === 0 ? j : j === 0 ? i : 0)),\n )\n for (let i = 1; i <= m; i++) {\n for (let j = 1; j <= n; j++) {\n dp[i]![j] =\n a[i - 1] === b[j - 1]\n ? dp[i - 1]![j - 1]!\n : 1 + Math.min(dp[i - 1]![j]!, dp[i]![j - 1]!, dp[i - 1]![j - 1]!)\n }\n }\n return dp[m]![n]!\n}\n\nfunction validateNode(\n node: unknown,\n path: string,\n errors: ValidationError[],\n componentNames: Set<string>,\n): void {\n if (typeof node !== 'object' || node === null) {\n errors.push({ path, message: 'Expected a component node object' })\n return\n }\n const n = node as Record<string, unknown>\n if (typeof n['component'] !== 'string') {\n errors.push({ path: `${path}.component`, message: 'component must be a string' })\n return\n }\n const componentName = n['component'] as string\n if (!componentNames.has(componentName)) {\n const suggestion = closestName(componentName, [...componentNames])\n const hint = suggestion ? ` Did you mean \"${suggestion}\"?` : ''\n errors.push({\n path: `${path}.component`,\n message: `Unknown component \"${componentName}\".${hint}`,\n })\n return\n }\n\n const nodeBind = (n['bind'] ?? {}) as Record<string, string>\n for (const [key, value] of Object.entries(nodeBind)) {\n if (typeof value !== 'string' || !DATA_REF_RE.test(value)) {\n errors.push({\n path: `${path}.bind.${key}`,\n message: `bind values must start with \"$data.\" — got \"${value}\"`,\n })\n }\n }\n\n const nodeEvents = (n['events'] ?? {}) as Record<string, string>\n for (const [key, value] of Object.entries(nodeEvents)) {\n if (typeof value !== 'string' || !ACTION_REF_RE.test(value)) {\n errors.push({\n path: `${path}.events.${key}`,\n message: `events values must start with \"$actions.\" — got \"${value}\"`,\n })\n }\n }\n\n if (Array.isArray(n['children'])) {\n for (let i = 0; i < n['children'].length; i++) {\n validateNode(\n n['children'][i] as ComponentNode,\n `${path}.children[${i}]`,\n errors,\n componentNames,\n )\n }\n }\n}\n\n/** Validate a ViewConfig object. Component names are checked against the provided set. */\nexport function validateView(\n config: unknown,\n componentNames: Set<string>,\n): { valid: boolean; errors: ValidationError[] } {\n const errors: ValidationError[] = []\n\n if (typeof config !== 'object' || config === null) {\n return { valid: false, errors: [{ path: '', message: 'Config must be an object' }] }\n }\n\n const c = config as Record<string, unknown>\n const view = c['view']\n\n if (typeof view !== 'object' || view === null) {\n return { valid: false, errors: [{ path: 'view', message: 'view must be an object' }] }\n }\n\n const v = view as Record<string, unknown>\n const regions = v['regions']\n\n if (typeof regions !== 'object' || regions === null) {\n errors.push({ path: 'view.regions', message: 'view.regions must be an object' })\n return { valid: false, errors }\n }\n\n for (const [regionName, nodes] of Object.entries(regions as Record<string, unknown>)) {\n if (!Array.isArray(nodes)) {\n errors.push({\n path: `view.regions.${regionName}`,\n message: `Region \"${regionName}\" must be an array of component nodes`,\n })\n continue\n }\n for (let i = 0; i < nodes.length; i++) {\n validateNode(\n nodes[i] as ComponentNode,\n `view.regions.${regionName}[${i}]`,\n errors,\n componentNames,\n )\n }\n }\n\n return { valid: errors.length === 0, errors }\n}\n","// Library-derived bound vocabulary (v40 T1).\n//\n// OpenUI's anti-hallucination mechanism is a system prompt generated from the\n// component library so a model can only emit registered components/props. This\n// module derives that bound vocabulary from the cascade manifests\n// (component.meta.ts → registry.json): per component → its props (name, type,\n// allowed enum values, required) plus variants/sizes. Because it is *derived*,\n// it can never drift from the components (grammar.test.ts asserts every name it\n// references exists in the registry).\n\nimport type { Registry } from './registry.js'\n\nexport interface GrammarProp {\n name: string\n required: boolean\n /** Raw TypeScript type string from the manifest. */\n type: string\n /** Allowed values, when `type` is a string-literal union (e.g. `'sm' | 'md'`). */\n enum?: string[]\n}\n\nexport interface GrammarComponent {\n name: string\n category: string\n props: GrammarProp[]\n variants: string[]\n sizes: string[]\n}\n\nexport interface ViewGrammar {\n components: GrammarComponent[]\n}\n\n/**\n * Parse a string-literal union type (`'a' | 'b' | \"c\"`) into its allowed\n * values. Returns `undefined` for any non-enum type (primitives, functions,\n * named types, object shapes) so the grammar only constrains what it can.\n */\nexport function parseEnum(type: string): string[] | undefined {\n const branches = type\n .split('|')\n .map((s) => s.trim())\n .filter((s) => s.length > 0)\n if (branches.length === 0) return undefined\n const values: string[] = []\n for (const branch of branches) {\n const quoted = branch.match(/^['\"](.+)['\"]$/)\n if (!quoted?.[1]) return undefined\n values.push(quoted[1])\n }\n return values\n}\n\n/**\n * Build the bound-vocabulary descriptor from the registry, optionally scoped to\n * a subset of component names (case-insensitive). Output is deterministic\n * (components and props sorted by name) for reproducible prompts and tests.\n */\n// Preference when two registry entries share a meta.name (e.g. a `component`\n// and a `layout` both named \"AppShell\"): the node-usable component wins.\nconst TYPE_RANK: Record<string, number> = {\n component: 0,\n block: 1,\n chart: 2,\n section: 3,\n layout: 4,\n}\n\nexport function buildGrammar(registry: Registry, subset?: string[]): ViewGrammar {\n const wanted = subset && subset.length > 0 ? new Set(subset.map((n) => n.toLowerCase())) : null\n\n // Dedupe by meta.name, keeping the highest-ranked (node-usable) entry.\n const canonical = new Map<string, (typeof registry.components)[number]>()\n for (const c of registry.components) {\n const key = c.meta.name.toLowerCase()\n const current = canonical.get(key)\n if (!current || (TYPE_RANK[c.type ?? ''] ?? 9) < (TYPE_RANK[current.type ?? ''] ?? 9)) {\n canonical.set(key, c)\n }\n }\n\n const components: GrammarComponent[] = [...canonical.values()]\n .filter(\n (c) => !wanted || wanted.has(c.meta.name.toLowerCase()) || wanted.has(c.name.toLowerCase()),\n )\n .map((c) => {\n const props: GrammarProp[] = (c.meta.props ?? [])\n .map((p) => {\n const values = parseEnum(p.type)\n return {\n name: p.name,\n required: p.required === true,\n type: p.type,\n ...(values ? { enum: values } : {}),\n }\n })\n .sort((a, b) => a.name.localeCompare(b.name))\n return {\n name: c.meta.name,\n category: c.category,\n props,\n variants: c.meta.variants ?? [],\n sizes: c.meta.sizes ?? [],\n }\n })\n .sort((a, b) => a.name.localeCompare(b.name))\n\n return { components }\n}\n\n/** Render one prop as `name`, `name*` (required), with enum choices or its type. */\nfunction formatProp(prop: GrammarProp): string {\n const mark = prop.required ? '*' : ''\n const value = prop.enum ? prop.enum.join('|') : prop.type\n return `${prop.name}${mark}: ${value}`\n}\n\n/**\n * Render the grammar as a compact, model-friendly table: one line per\n * component. Terser than verbose JSON; a `*` marks a required prop.\n *\n * Badge(size: sm|md, variant: default|secondary|success|warning|destructive|outline)\n */\nexport function formatGrammar(grammar: ViewGrammar): string {\n return grammar.components\n .map((c) => `${c.name}(${c.props.map(formatProp).join(', ')})`)\n .join('\\n')\n}\n","import type { ViewConfig } from './validate.js'\nimport { validateView } from './validate.js'\nimport type { Registry } from './registry.js'\nimport { buildGrammar, formatGrammar } from './grammar.js'\n\ninterface ScaffoldViewInput {\n description: string\n components?: string[]\n}\n\n/** Simple keyword matcher — returns region layout name based on description keywords. */\nfunction pickLayout(description: string): string {\n const d = description.toLowerCase()\n if (d.includes('dashboard') || d.includes('stats') || d.includes('kpi')) return 'dashboard'\n if (d.includes('settings') || d.includes('preferences') || d.includes('config')) return 'settings'\n if (d.includes('login') || d.includes('auth') || d.includes('sign')) return 'auth'\n return 'none'\n}\n\n/** Pick sensible components from the registry matching keywords in description. */\nfunction pickComponents(description: string, registry: Registry, explicit?: string[]): string[] {\n if (explicit && explicit.length > 0) return explicit.map((c) => c.toLowerCase())\n const d = description.toLowerCase()\n const candidates: string[] = []\n for (const entry of registry.components) {\n const name = entry.meta.name.toLowerCase()\n const tags = entry.tags.join(' ').toLowerCase()\n if (d.includes(name) || tags.split(' ').some((t) => d.includes(t))) {\n candidates.push(entry.meta.name)\n }\n }\n // Always add at least one component\n if (candidates.length === 0) candidates.push('Badge')\n return candidates.slice(0, 4)\n}\n\nfunction makeNode(\n componentName: string,\n registry: Registry,\n): { component: string; props?: Record<string, string | number | boolean> } {\n const entry = registry.components.find(\n (c) => c.meta.name.toLowerCase() === componentName.toLowerCase(),\n )\n if (!entry) return { component: componentName }\n const props: Record<string, string | number | boolean> = {}\n for (const prop of entry.meta.props ?? []) {\n if (prop.required && prop.default !== undefined) {\n props[prop.name] = prop.default\n } else if (\n prop.default !== undefined &&\n ['string', 'number', 'boolean'].includes(typeof prop.default)\n ) {\n // Skip defaults that are complex\n }\n }\n return Object.keys(props).length > 0\n ? { component: entry.meta.name, props }\n : { component: entry.meta.name }\n}\n\nexport function scaffoldView(\n input: ScaffoldViewInput,\n registry: Registry,\n): {\n config: ViewConfig\n errors: { path: string; message: string }[]\n /** Bound-vocabulary grammar (v40 T1) for the scaffolded components, so a caller gets both a starter scaffold and the allowed props/enums to refine it. */\n grammar: string\n} {\n const layout = pickLayout(input.description)\n const componentNames = pickComponents(input.description, registry, input.components)\n\n const config: ViewConfig = {\n $schema:\n 'https://raw.githubusercontent.com/cascivo/cascivo/main/packages/render/schema/view.v1.json',\n version: 1,\n view: {\n ...(layout !== 'none' ? { layout } : {}),\n regions: {\n main: componentNames.map((name) => makeNode(name, registry)),\n },\n },\n }\n\n const validNames = new Set(registry.components.map((c) => c.meta.name))\n const { errors } = validateView(config, validNames)\n const grammar = formatGrammar(buildGrammar(registry, componentNames))\n return { config, errors, grammar }\n}\n","// Generation prompt derived from the bound vocabulary (v40 T1).\n//\n// Composes the system prompt an LLM needs to emit valid `ViewConfig` JSON that\n// is restricted to cascivo's real components, props, and enum values — the\n// OpenUI \"system prompt from the component library\" anti-hallucination\n// mechanism, applied to the format cascivo already ships and dogfoods\n// (@cascivo/render). See docs/ROADMAP-V40.md.\n\nimport { buildGrammar, formatGrammar } from './grammar.js'\nimport type { Registry } from './registry.js'\n\nexport interface GenerationPromptOptions {\n /** Scope the vocabulary to a subset of component names. Defaults to all. */\n components?: string[]\n}\n\nconst SCHEMA_DOC = `A ViewConfig is a JSON object:\n\n{\n \"version\": 1,\n \"view\": {\n \"layout\": \"<optional layout name, e.g. dashboard | settings | auth>\",\n \"regions\": {\n \"<regionName>\": [ <ComponentNode>, ... ]\n }\n }\n}\n\nA ComponentNode is:\n\n{\n \"component\": \"<one of the registered component names below>\",\n \"props\": { \"<propName>\": <value> },\n \"bind\": { \"<propName>\": \"$data.<path>\" },\n \"events\": { \"<eventPropName>\": \"$actions.<name>\" },\n \"children\": <ComponentNode[] | string | { \"$t\": \"<i18n.key>\" }>\n}\n\nRules:\n- \"component\" MUST be one of the registered components listed below — never invent one.\n- Only use props listed for that component; enum props MUST use one of the listed values.\n- \"bind\" values are host-data references and MUST start with \"$data.\".\n- \"events\" values are host-action references and MUST start with \"$actions.\".\n- \"children\" is an array of nodes, a plain string, or an i18n ref { \"$t\": \"key\" }.\n- Output ONLY the JSON ViewConfig — no prose, no markdown fences.`\n\n/**\n * Build the bound-vocabulary system prompt for emitting `ViewConfig` JSON.\n * Parameterizable by an optional component subset (defaults to the full\n * registry).\n */\nexport function buildGenerationPrompt(\n registry: Registry,\n options: GenerationPromptOptions = {},\n): string {\n const grammar = buildGrammar(registry, options.components)\n const vocabulary = formatGrammar(grammar)\n\n const sections = [\n 'You generate UI as a cascivo ViewConfig — a JSON description rendered by @cascivo/render <CascadeView />.',\n SCHEMA_DOC,\n 'Registered components (allowed vocabulary — `name*` marks a required prop):',\n vocabulary,\n // EXTENSION POINT (v40 T3, optional): when the `cvl` compact DSL ships, append a\n // \"cvl syntax\" section here so an agent can be asked to emit cvl instead of JSON.\n ]\n\n return sections.join('\\n\\n')\n}\n","import { existsSync, readFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nexport interface TokenCatalogEntry {\n name: string\n value: string\n layer: 'primitive' | 'semantic' | 'component'\n group: string\n resolvedDefault: string | null\n resolvesPerTheme: boolean\n}\n\nexport interface TokenCatalog {\n generatedAt: string\n count: number\n tokens: TokenCatalogEntry[]\n}\n\ntype FetchFn = (url: string, init?: RequestInit) => Promise<Response>\n\nconst HERE = dirname(fileURLToPath(import.meta.url))\nconst CATALOG_BASE_URL = 'https://cascivo.com'\n\nexport async function loadTokenCatalog(fetchFn?: FetchFn): Promise<TokenCatalog> {\n const localPaths = [\n join(HERE, '..', '..', '..', 'apps', 'docs', 'public', 'tokens.catalog.json'),\n join(HERE, 'tokens.catalog.json'),\n ]\n for (const p of localPaths) {\n if (existsSync(p)) return JSON.parse(readFileSync(p, 'utf8')) as TokenCatalog\n }\n const url = `${CATALOG_BASE_URL}/tokens.catalog.json`\n const fn = fetchFn ?? fetch\n const res = await fn(url)\n if (!res.ok) throw new Error(`Failed to fetch token catalog: ${res.status}`)\n return res.json() as Promise<TokenCatalog>\n}\n","import { existsSync, readFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nexport interface VariantToken {\n name: string\n layer: 'primitive' | 'semantic' | 'component'\n group: string\n role?: string\n slot?: string\n byTheme: Record<string, string | null>\n}\n\nexport interface VariantMatrix {\n generatedAt: string\n themes: string[]\n families: Record<string, Record<string, string>>\n tokens: VariantToken[]\n}\n\ntype FetchFn = (url: string, init?: RequestInit) => Promise<Response>\n\nconst HERE = dirname(fileURLToPath(import.meta.url))\nconst BASE_URL = 'https://cascivo.com'\n\nexport async function loadVariantMatrix(fetchFn?: FetchFn): Promise<VariantMatrix> {\n const localPaths = [\n join(HERE, '..', '..', '..', 'apps', 'docs', 'public', 'tokens.variants.json'),\n join(HERE, 'tokens.variants.json'),\n ]\n for (const p of localPaths) {\n if (existsSync(p)) return JSON.parse(readFileSync(p, 'utf8')) as VariantMatrix\n }\n const url = `${BASE_URL}/tokens.variants.json`\n const fn = fetchFn ?? fetch\n const res = await fn(url)\n if (!res.ok) throw new Error(`Failed to fetch variant matrix: ${res.status}`)\n return res.json() as Promise<VariantMatrix>\n}\n","/**\n * Shadow-sandbox component validator.\n *\n * Runs cascivo's own structural invariants over a candidate component's source\n * (TSX + CSS) *before* it is written to disk, so an agent can loop until the\n * source passes instead of emitting code that the repo's gates would later\n * reject. This is a static structural evaluation — not a full browser render —\n * but it catches the mistakes LLMs actually make against this design system:\n * banned React hooks, off-scale breakpoint literals, missing static fallbacks\n * for progressive CSS, and hallucinated `--cascivo-*` tokens.\n *\n * The checks mirror the repo gates:\n * - use-signals-gate / authoring rules → banned hooks\n * - breakpoint:check → off-scale @media/@container widths\n * - fallback:check → @function/if() static-fallback contract\n * - token catalog (closed set) → no hallucinated tokens\n */\n\nexport type Severity = 'error' | 'warning'\n\nexport interface ComponentViolation {\n rule: string\n severity: Severity\n line: number\n detail: string\n}\n\nexport interface ValidateComponentInput {\n /** Component TSX source. */\n tsx?: string\n /** Component CSS (module or plain) source. */\n css?: string\n /** Component name, for messages only. */\n name?: string\n}\n\nexport interface ValidateComponentOptions {\n /**\n * The closed set of valid `--cascivo-*` token names. When provided, any\n * `var(--cascivo-…)` reference outside this set is flagged as hallucinated.\n */\n tokenNames?: ReadonlySet<string>\n}\n\nexport interface ValidateComponentResult {\n valid: boolean\n name?: string\n violations: ComponentViolation[]\n}\n\n// Hooks that cascivo components must never use — signals replace them.\nconst BANNED_HOOKS = ['useState', 'useEffect', 'useLayoutEffect', 'useContext', 'useReducer']\n\n// Canonical breakpoint width literals (the only ones allowed in @media/@container).\nconst CANONICAL_WIDTHS = new Set([\n '30rem',\n '40rem',\n '64rem',\n '80rem',\n '480px',\n '640px',\n '1024px',\n '1280px',\n])\n\nfunction lineOf(source: string, index: number): number {\n let line = 1\n for (let i = 0; i < index && i < source.length; i++) {\n if (source[i] === '\\n') line++\n }\n return line\n}\n\n/** Detect banned React hooks in TSX (usage or import). */\nfunction checkBannedHooks(tsx: string): ComponentViolation[] {\n const violations: ComponentViolation[] = []\n for (const hook of BANNED_HOOKS) {\n const re = new RegExp(`\\\\b${hook}\\\\b`, 'g')\n let m: RegExpExecArray | null\n while ((m = re.exec(tsx)) !== null) {\n violations.push({\n rule: 'banned-hook',\n severity: 'error',\n line: lineOf(tsx, m.index),\n detail:\n hook === 'useEffect'\n ? `${hook} is banned — use useSignalEffect for DOM side effects`\n : `${hook} is banned — use useSignal/useComputed from @cascivo/core`,\n })\n }\n }\n return violations\n}\n\n/** Detect off-scale width literals in @media / @container conditions. */\nfunction checkBreakpoints(css: string): ComponentViolation[] {\n const violations: ComponentViolation[] = []\n const widthCondRe =\n /(?:min-width|max-width|width|min-inline-size|max-inline-size|inline-size)\\s*:\\s*([\\d.]+(?:rem|px|em))/g\n const lines = css.split('\\n')\n for (let i = 0; i < lines.length; i++) {\n const trimmed = (lines[i] ?? '').trim()\n if (!trimmed.startsWith('@media') && !trimmed.startsWith('@container')) continue\n if (\n /prefers|forced|pointer|hover|aspect|color|resolution|orientation|print|screen/.test(trimmed)\n )\n continue\n let m: RegExpExecArray | null\n widthCondRe.lastIndex = 0\n while ((m = widthCondRe.exec(trimmed)) !== null) {\n const value = m[1] ?? ''\n if (!CANONICAL_WIDTHS.has(value)) {\n violations.push({\n rule: 'off-scale-breakpoint',\n severity: 'error',\n line: i + 1,\n detail: `Off-scale width \"${value}\" — use 30rem/40rem/64rem/80rem`,\n })\n }\n }\n }\n return violations\n}\n\nconst isFunctionCall = (value: string) => /--[\\w-]+\\(/.test(value)\nconst isIfExpression = (value: string) => /\\bif\\s*\\(/.test(value)\n\n/** Enforce the @function / if() static-fallback contract. */\nfunction checkFallbacks(css: string): ComponentViolation[] {\n const violations: ComponentViolation[] = []\n const lines = css.split('\\n')\n let inSupports = false\n let supportsDepth = 0\n let baseSupportsDepth = 0\n interface Block {\n properties: Map<string, boolean>\n }\n const stack: Block[] = []\n\n for (let i = 0; i < lines.length; i++) {\n const line = (lines[i] ?? '').trim()\n if (/^@supports\\b/.test(line)) {\n inSupports = true\n baseSupportsDepth = supportsDepth\n }\n const opens = (line.match(/\\{/g) ?? []).length\n const closes = (line.match(/\\}/g) ?? []).length\n for (let j = 0; j < opens; j++) {\n stack.push({ properties: new Map() })\n supportsDepth++\n }\n for (let j = 0; j < closes; j++) {\n if (stack.length > 0) stack.pop()\n supportsDepth--\n if (supportsDepth <= baseSupportsDepth) inSupports = false\n }\n const declMatch = line.match(/^([\\w-]+)\\s*:\\s*(.+?)\\s*;?\\s*$/)\n if (!declMatch) continue\n const property = declMatch[1]!\n const value = declMatch[2]!\n if (isFunctionCall(value) || isIfExpression(value)) {\n let hasFallback = inSupports\n if (!hasFallback) {\n for (const block of stack) {\n if (block.properties.get(property)) {\n hasFallback = true\n break\n }\n }\n }\n if (!hasFallback) {\n violations.push({\n rule: 'missing-css-fallback',\n severity: 'error',\n line: i + 1,\n detail: `\"${property}\" uses @function/if() with no preceding static fallback`,\n })\n }\n } else if (stack.length > 0) {\n stack[stack.length - 1]!.properties.set(property, true)\n }\n }\n return violations\n}\n\n/** Flag `var(--cascivo-…)` references that are not in the closed token set. */\nfunction checkTokens(css: string, tokenNames: ReadonlySet<string>): ComponentViolation[] {\n if (tokenNames.size === 0) return []\n const violations: ComponentViolation[] = []\n const re = /var\\(\\s*(--cascivo-[\\w-]+)/g\n let m: RegExpExecArray | null\n const seen = new Set<string>()\n while ((m = re.exec(css)) !== null) {\n const token = m[1]!\n if (tokenNames.has(token) || seen.has(token)) continue\n seen.add(token)\n violations.push({\n rule: 'unknown-token',\n severity: 'error',\n line: lineOf(css, m.index),\n detail: `\"${token}\" is not in the cascivo token catalog (hallucinated token)`,\n })\n }\n return violations\n}\n\n/** Run all structural invariants over a candidate component's source. */\nexport function validateComponentSource(\n input: ValidateComponentInput,\n options: ValidateComponentOptions = {},\n): ValidateComponentResult {\n const violations: ComponentViolation[] = []\n if (input.tsx) violations.push(...checkBannedHooks(input.tsx))\n if (input.css) {\n violations.push(...checkBreakpoints(input.css))\n violations.push(...checkFallbacks(input.css))\n if (options.tokenNames) violations.push(...checkTokens(input.css, options.tokenNames))\n }\n violations.sort((a, b) => a.line - b.line)\n return {\n valid: violations.every((v) => v.severity !== 'error'),\n ...(input.name ? { name: input.name } : {}),\n violations,\n }\n}\n","import { existsSync, readFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nexport interface ContextRelated {\n name: string\n relationship: string\n reason: string\n}\n\nexport interface ContextAntiPattern {\n bad: string\n good: string\n why: string\n}\n\nexport interface ContextFlexibility {\n area: string\n level: string\n note: string\n}\n\nexport interface ComponentIntent {\n whenToUse: string[]\n whenNotToUse: string[]\n antiPatterns: ContextAntiPattern[]\n related: ContextRelated[]\n a11yRationale?: string\n flexibility?: ContextFlexibility[]\n}\n\nexport interface ContextComponent {\n name: string\n category: string\n description: string\n intent: ComponentIntent\n contextUrl: string\n /** Copy-pasteable system-prompt snippet that pins an LLM to this component. */\n aiPrompt?: string\n}\n\nexport interface ContextBundle {\n generatedAt: string\n tagline: string\n authoringRules: string[]\n tokenCatalogUrl: string\n components: ContextComponent[]\n}\n\ntype FetchFn = (url: string, init?: RequestInit) => Promise<Response>\n\nconst HERE = dirname(fileURLToPath(import.meta.url))\nconst CONTEXT_BASE_URL = 'https://cascivo.com'\n\nexport async function loadContext(fetchFn?: FetchFn): Promise<ContextBundle> {\n const localPaths = [\n join(HERE, '..', '..', '..', 'apps', 'docs', 'public', 'context.json'),\n join(HERE, 'context.json'),\n ]\n for (const p of localPaths) {\n if (existsSync(p)) return JSON.parse(readFileSync(p, 'utf8')) as ContextBundle\n }\n const url = `${CONTEXT_BASE_URL}/context.json`\n const fn = fetchFn ?? fetch\n const res = await fn(url)\n if (!res.ok) throw new Error(`Failed to fetch context bundle: ${res.status}`)\n return res.json() as Promise<ContextBundle>\n}\n\nexport async function loadComponentMarkdown(\n name: string,\n fetchFn?: FetchFn,\n): Promise<string | null> {\n const slug = name.toLowerCase().replace(/\\s+/g, '-')\n const localPaths = [\n join(HERE, '..', '..', '..', 'apps', 'docs', 'public', 'context', `${slug}.md`),\n join(HERE, 'context', `${slug}.md`),\n ]\n for (const p of localPaths) {\n if (existsSync(p)) return readFileSync(p, 'utf8')\n }\n const url = `${CONTEXT_BASE_URL}/context/${slug}.md`\n const fn = fetchFn ?? fetch\n try {\n const res = await fn(url)\n if (!res.ok) return null\n return res.text()\n } catch {\n return null\n }\n}\n","import type { ContextComponent } from './context.js'\n\nexport interface SelectRelated {\n name: string\n relationship: string\n reason: string\n}\n\nexport interface SelectResult {\n name: string\n score: number\n why: string\n /** When NOT to use this pick — lets an agent disqualify a wrong match. */\n whenNotToUse: string[]\n /** Related components (alternatives, pairs-with) to consider instead/alongside. */\n related: SelectRelated[]\n}\n\n// Minimum length for a need word to be scored (filters out articles, prepositions, etc.)\nconst MIN_WORD_LEN = 3\n\nfunction words(text: string): string[] {\n return (text.toLowerCase().match(/\\b\\w+\\b/g) ?? []).filter((w) => w.length >= MIN_WORD_LEN)\n}\n\nfunction countMatches(needWords: string[], text: string): string[] {\n const lower = text.toLowerCase()\n return needWords.filter((w) => lower.includes(w))\n}\n\nexport function selectComponent(need: string, components: ContextComponent[]): SelectResult[] {\n const needWords = words(need)\n if (needWords.length === 0) return []\n\n const scored = components.map((c) => {\n const whenToUseText = c.intent.whenToUse.join(' ')\n const whenNotToUseText = c.intent.whenNotToUse.join(' ')\n\n const whenToUseMatches = countMatches(needWords, whenToUseText)\n const descMatches = countMatches(needWords, c.description)\n const penaltyMatches = countMatches(needWords, whenNotToUseText)\n\n const score = whenToUseMatches.length * 2 + descMatches.length - penaltyMatches.length * 3\n\n // Build why from the best-matching whenToUse sentence\n let why = ''\n if (whenToUseMatches.length > 0) {\n const bestSentence = c.intent.whenToUse\n .map((s) => ({ s, count: countMatches(needWords, s).length }))\n .filter((x) => x.count > 0)\n .sort((a, b) => b.count - a.count)[0]?.s\n why = bestSentence\n ? `Matched: ${whenToUseMatches.map((w) => `'${w}'`).join(', ')} in whenToUse — \"${bestSentence}\"`\n : `Matched: ${whenToUseMatches.map((w) => `'${w}'`).join(', ')} in description`\n } else if (descMatches.length > 0) {\n why = `Matched: ${descMatches.map((w) => `'${w}'`).join(', ')} in description`\n }\n\n return {\n name: c.name,\n score,\n why,\n whenNotToUse: c.intent.whenNotToUse ?? [],\n related: c.intent.related ?? [],\n }\n })\n\n // First pass: top 3 by score for related bonus\n const top3Names = new Set(\n [...scored]\n .sort((a, b) => b.score - a.score || a.name.localeCompare(b.name))\n .slice(0, 3)\n .map((r) => r.name),\n )\n\n // Apply related bonus: +1 if a top-3 component points at this component\n const relatedBonus = new Map<string, number>()\n for (const r of scored) {\n if (!top3Names.has(r.name)) continue\n for (const rel of r.related) {\n relatedBonus.set(rel.name, (relatedBonus.get(rel.name) ?? 0) + 1)\n }\n }\n\n const final = scored.map((r) => ({\n name: r.name,\n score: r.score + (relatedBonus.get(r.name) ?? 0),\n why: r.why,\n whenNotToUse: r.whenNotToUse,\n related: r.related,\n }))\n\n return final\n .filter((r) => r.score >= 0)\n .sort((a, b) => b.score - a.score || a.name.localeCompare(b.name))\n .slice(0, 5)\n}\n","import { spawnSync } from 'node:child_process'\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { z } from 'zod'\nimport {\n fetchDirectory,\n fetchRegistryIndex,\n getComponent,\n getEnvRegistries,\n listComponents,\n loadRegistry,\n mergeRegistries,\n searchComponents,\n type Registry,\n} from './registry.js'\nimport { generateThemeCss } from './theme.js'\nimport { scaffoldPage } from './scaffold.js'\nimport { validateView } from './validate.js'\nimport { scaffoldView } from './scaffold-view.js'\nimport { buildGrammar, formatGrammar } from './grammar.js'\nimport { buildGenerationPrompt } from './prompt.js'\nimport { loadTokenCatalog } from './tokens.js'\nimport { loadVariantMatrix } from './variants.js'\nimport { validateComponentSource } from './validate-component.js'\nimport { loadContext, loadComponentMarkdown } from './context.js'\nimport { selectComponent } from './select.js'\n\ntype FetchFn = (url: string, init?: RequestInit) => Promise<Response>\n\nexport interface ServerOptions {\n registryPath?: string\n version?: string\n /** Injectable fetch function — used for testing multi-registry features. */\n fetchFn?: FetchFn\n}\n\nconst json = (value: unknown) => ({\n content: [{ type: 'text' as const, text: JSON.stringify(value, null, 2) }],\n})\n\nconst text = (value: string) => ({ content: [{ type: 'text' as const, text: value }] })\n\nconst error = (message: string) => ({\n content: [{ type: 'text' as const, text: message }],\n isError: true,\n})\n\n/** Build a configured McpServer exposing the cascade component registry. */\nexport function createServer(options: ServerOptions = {}): McpServer {\n const registry: Registry = loadRegistry(options.registryPath)\n const fetchFn = options.fetchFn\n\n const server = new McpServer({\n name: '@cascivo/mcp',\n version: options.version ?? '0.0.0',\n })\n\n server.registerTool(\n 'list_registries',\n {\n title: 'List registries',\n description:\n 'List available component registries: the cascade directory plus any configured via CASCADE_REGISTRIES env.',\n inputSchema: {},\n },\n async () => {\n const directory = await fetchDirectory(fetchFn)\n const env = getEnvRegistries()\n const entries = mergeRegistries(directory, env)\n return json(\n entries.map(({ namespace, name, description, verified, homepage }) => ({\n namespace,\n name,\n description,\n verified: verified ?? false,\n homepage,\n })),\n )\n },\n )\n\n server.registerTool(\n 'list_components',\n {\n title: 'List components',\n description: 'List all cascade components, optionally filtered by category and/or type.',\n inputSchema: {\n category: z\n .enum(['inputs', 'display', 'overlay', 'navigation', 'feedback', 'chart'])\n .optional()\n .describe('Filter by component category'),\n type: z\n .enum(['component', 'layout', 'block', 'chart', 'flow', 'editor'])\n .optional()\n .describe('Filter by entry type'),\n },\n },\n ({ category, type }) => json(listComponents(registry, category, type)),\n )\n\n server.registerTool(\n 'get_component',\n {\n title: 'Get component',\n description:\n 'Get the full manifest (props, states, tokens, a11y, examples) for one component.',\n inputSchema: {\n name: z.string().describe('Component name, e.g. \"button\"'),\n registry: z\n .string()\n .optional()\n .describe('Namespace of an external registry, e.g. \"@myns\". Omit for the default.'),\n },\n },\n async ({ name, registry: ns }) => {\n if (ns) {\n const env = getEnvRegistries()\n const directory = await fetchDirectory(fetchFn)\n const entries = mergeRegistries(directory, env)\n const entry = entries.find((e) => e.namespace === ns)\n if (!entry) return error(`Registry \"${ns}\" not found.`)\n const remoteRegistry = await fetchRegistryIndex(entry.registryUrl, fetchFn)\n if (!remoteRegistry) return error(`Failed to fetch registry index for \"${ns}\".`)\n const meta = getComponent(remoteRegistry, name)\n return meta ? json(meta) : error(`Component \"${name}\" not found in registry \"${ns}\".`)\n }\n const meta = getComponent(registry, name)\n return meta ? json(meta) : error(`Component \"${name}\" not found.`)\n },\n )\n\n server.registerTool(\n 'search_components',\n {\n title: 'Search components',\n description: 'Fuzzy search components by name, tags, or description.',\n inputSchema: {\n query: z.string().describe('Search query'),\n registry: z\n .string()\n .optional()\n .describe('Namespace of an external registry, e.g. \"@myns\". Omit for the default.'),\n },\n },\n async ({ query, registry: ns }) => {\n if (ns) {\n const env = getEnvRegistries()\n const directory = await fetchDirectory(fetchFn)\n const entries = mergeRegistries(directory, env)\n const entry = entries.find((e) => e.namespace === ns)\n if (!entry) return error(`Registry \"${ns}\" not found.`)\n const remoteRegistry = await fetchRegistryIndex(entry.registryUrl, fetchFn)\n if (!remoteRegistry) return error(`Failed to fetch registry index for \"${ns}\".`)\n return json(searchComponents(remoteRegistry, query))\n }\n return json(searchComponents(registry, query))\n },\n )\n\n server.registerTool(\n 'add_to_project',\n {\n title: 'Add to project',\n description: 'Add a component to the current project by running the cascade CLI.',\n inputSchema: {\n name: z.string().describe('Component name to add'),\n outputDir: z.string().optional().describe('Directory to write the component into'),\n },\n },\n ({ name, outputDir }) => {\n const env = outputDir ? { ...process.env, CASCIVO_OUTPUT_DIR: outputDir } : process.env\n const result = spawnSync('npx', ['-y', 'cascivo', 'add', name], { encoding: 'utf8', env })\n if (result.status !== 0) {\n return error(result.stderr || result.error?.message || `Failed to add \"${name}\".`)\n }\n return text(result.stdout || `Added ${name}.`)\n },\n )\n\n server.registerTool(\n 'create_theme',\n {\n title: 'Create theme',\n description: 'Generate a cascade theme CSS file from three colors.',\n inputSchema: {\n primary: z.string().describe('Primary / interactive color (any CSS color)'),\n neutral: z.string().describe('Base neutral color for surfaces and text'),\n accent: z.string().describe('Secondary accent color (info / focus)'),\n name: z.string().optional().describe('Theme name (default: \"custom\")'),\n },\n },\n ({ primary, neutral, accent, name }) =>\n text(generateThemeCss({ primary, neutral, accent }, name)),\n )\n\n server.registerTool(\n 'scaffold_page',\n {\n title: 'Scaffold page (deprecated)',\n description:\n '[Deprecated — use scaffold_view instead] Generate a JSX page layout from a description.',\n inputSchema: {\n description: z.string().describe('What the page is for'),\n components: z.array(z.string()).optional().describe('Components to include'),\n },\n },\n ({ description, components }) => {\n const { config } = scaffoldView(\n { description, ...(components ? { components } : {}) },\n registry,\n )\n return text(\n `[Deprecated] Use scaffold_view for config-first output. JSX scaffold:\\n\\n${scaffoldPage(components ? { description, components } : { description })}\\n\\n--- scaffold_view output ---\\n${JSON.stringify(config, null, 2)}`,\n )\n },\n )\n\n server.registerTool(\n 'validate_view',\n {\n title: 'Validate view config',\n description:\n 'Validate a CascadeView JSON config against the registry. Returns errors with exact paths.',\n inputSchema: {\n config: z.record(z.string(), z.unknown()).describe('The ViewConfig object to validate'),\n },\n },\n ({ config }) => {\n const componentNames = new Set(registry.components.map((c) => c.meta.name))\n const result = validateView(config, componentNames)\n return json(result)\n },\n )\n\n server.registerTool(\n 'scaffold_view',\n {\n title: 'Scaffold view config',\n description:\n 'Generate a valid starter ViewConfig from a description. Always validates before returning.',\n inputSchema: {\n description: z.string().describe('What the page/view is for'),\n components: z.array(z.string()).optional().describe('Component names to include'),\n },\n },\n ({ description, components }) => {\n const { config, errors, grammar } = scaffoldView(\n { description, ...(components ? { components } : {}) },\n registry,\n )\n if (errors.length > 0) {\n return json({ valid: false, errors, config, grammar })\n }\n return json({ valid: true, config, grammar })\n },\n )\n\n server.registerTool(\n 'scaffold_flow',\n {\n title: 'Scaffold a flow diagram',\n description:\n 'Generate a starter declarative <Flow nodes edges /> (from @cascivo/flow) for a node/edge diagram — flowchart, DAG, or pipeline. Returns serializable nodes/edges plus ready-to-paste JSX. Edit the labels/edges to match the intent.',\n inputSchema: {\n description: z.string().describe('What the diagram represents'),\n steps: z\n .array(z.string())\n .optional()\n .describe(\n 'Ordered step labels; consecutive steps are connected. Omit for a 3-step starter.',\n ),\n layout: z\n .enum(['none', 'grid', 'layered'])\n .optional()\n .describe('Optional auto-layout. Default \"layered\".'),\n },\n },\n ({ description, steps, layout }) => {\n const labels = steps && steps.length > 0 ? steps : ['Source', 'Process', 'Sink']\n const nodes = labels.map((label, i) => ({\n id: `n${i + 1}`,\n position: { x: i * 240, y: 0 },\n data: { label },\n }))\n const edges = labels.slice(1).map((_, i) => ({\n id: `e${i + 1}`,\n source: `n${i + 1}`,\n target: `n${i + 2}`,\n animated: true,\n }))\n const lay = layout ?? 'layered'\n const layoutProp = lay === 'none' ? '' : ` layout=\"${lay}\"`\n const code = `import { Flow } from '@cascivo/flow'\nimport '@cascivo/flow/styles.css'\n\n// ${description}\nexport function Diagram() {\n return (\n <Flow\n style={{ height: 360 }}\n background\n controls${layoutProp}\n nodes={${JSON.stringify(nodes)}}\n edges={${JSON.stringify(edges)}}\n />\n )\n}`\n return json({ nodes, edges, layout: lay, code })\n },\n )\n\n server.registerTool(\n 'get_view_grammar',\n {\n title: 'Get view grammar',\n description:\n \"Get the bound-vocabulary grammar + system prompt for generating valid ViewConfig JSON, derived from the component manifests. Use this to constrain an LLM to cascivo's real components, props, and enum values (anti-hallucination). Optionally scope to a subset of components.\",\n inputSchema: {\n components: z\n .array(z.string())\n .optional()\n .describe('Scope the vocabulary to these component names. Omit for the full registry.'),\n },\n },\n ({ components }) => {\n const grammar = buildGrammar(registry, components)\n return json({\n grammar: formatGrammar(grammar),\n prompt: buildGenerationPrompt(registry, components ? { components } : {}),\n components: grammar.components,\n })\n },\n )\n\n server.registerTool(\n 'get_tokens',\n {\n title: 'Get tokens',\n description:\n 'Get the cascade token catalog (closed set). Agents must select from this catalog rather than hard-coding values.',\n inputSchema: {\n group: z\n .string()\n .optional()\n .describe('Filter by token group, e.g. \"color\", \"space\", \"radius\"'),\n layer: z\n .enum(['primitive', 'semantic', 'component'])\n .optional()\n .describe('Filter by layer'),\n },\n },\n async ({ group, layer }) => {\n try {\n const catalog = await loadTokenCatalog(fetchFn)\n let tokens = catalog.tokens\n if (group) tokens = tokens.filter((t) => t.group === group)\n if (layer) tokens = tokens.filter((t) => t.layer === layer)\n return json({ count: tokens.length, tokens })\n } catch (e) {\n return error(`Token catalog unavailable: ${e instanceof Error ? e.message : String(e)}`)\n }\n },\n )\n\n server.registerTool(\n 'get_variant_matrix',\n {\n title: 'Get variant matrix',\n description:\n 'Get the deterministic token variant matrix: a map from design intent (a colour role + state slot, e.g. accent + hover) to the exact token name, plus every semantic/component token resolved to a concrete value in each theme. Use this to answer \"what is the warm theme\\'s accent-hover value?\" or \"which token is the active state of primary?\" without guessing how layered theme CSS resolves.',\n inputSchema: {\n role: z\n .string()\n .optional()\n .describe('Filter to one colour role, e.g. \"accent\", \"primary\", \"destructive\"'),\n theme: z\n .string()\n .optional()\n .describe('Restrict the per-theme values to a single theme, e.g. \"warm\"'),\n },\n },\n async ({ role, theme }) => {\n try {\n const matrix = await loadVariantMatrix(fetchFn)\n if (theme && !matrix.themes.includes(theme)) {\n return error(`Unknown theme \"${theme}\". Available: ${matrix.themes.join(', ')}`)\n }\n const pickTheme = (byTheme: Record<string, string | null>) =>\n theme ? { [theme]: byTheme[theme] ?? null } : byTheme\n let tokens = matrix.tokens\n let families = matrix.families\n if (role) {\n tokens = tokens.filter((t) => t.role === role)\n families = matrix.families[role] ? { [role]: matrix.families[role] } : {}\n if (tokens.length === 0) {\n const available = Object.keys(matrix.families).join(', ')\n return error(`No colour role \"${role}\". Available roles: ${available}`)\n }\n }\n return json({\n themes: theme ? [theme] : matrix.themes,\n families,\n tokens: tokens.map((t) => ({ ...t, byTheme: pickTheme(t.byTheme) })),\n })\n } catch (e) {\n return error(`Variant matrix unavailable: ${e instanceof Error ? e.message : String(e)}`)\n }\n },\n )\n\n server.registerTool(\n 'validate_component',\n {\n title: 'Validate component (shadow sandbox)',\n description:\n \"Run cascivo's structural invariants over candidate component source (TSX and/or CSS) before writing it to disk. Catches banned React hooks, off-scale @media/@container breakpoints, missing static fallbacks for progressive CSS (@function/if()), and hallucinated --cascivo-* tokens. Use this to self-correct generated code in a loop until `valid` is true.\",\n inputSchema: {\n tsx: z.string().optional().describe('Component TSX source'),\n css: z.string().optional().describe('Component CSS (module or plain) source'),\n name: z.string().optional().describe('Component name (for messages only)'),\n },\n },\n async ({ tsx, css, name }) => {\n let tokenNames: Set<string> | undefined\n try {\n const catalog = await loadTokenCatalog(fetchFn)\n tokenNames = new Set(catalog.tokens.map((t) => t.name))\n } catch {\n // Token catalog is optional — skip the hallucination check if unavailable.\n }\n const result = validateComponentSource(\n { ...(tsx ? { tsx } : {}), ...(css ? { css } : {}), ...(name ? { name } : {}) },\n tokenNames ? { tokenNames } : {},\n )\n return json(result)\n },\n )\n\n server.registerTool(\n 'get_context',\n {\n title: 'Get context',\n description:\n 'Get intent, whenToUse/whenNotToUse, and authoring guidance for one component by name.',\n inputSchema: {\n name: z.string().describe('Component name, e.g. \"Toast\"'),\n },\n },\n async ({ name }) => {\n try {\n const ctx = await loadContext(fetchFn)\n const target = name.toLowerCase()\n const component = ctx.components.find((c) => c.name.toLowerCase() === target)\n if (!component) {\n const available = ctx.components.map((c) => c.name).join(', ')\n return error(`Component \"${name}\" not found. Available: ${available}`)\n }\n const md = await loadComponentMarkdown(component.name, fetchFn)\n return json({\n name: component.name,\n category: component.category,\n description: component.description,\n intent: component.intent,\n contextUrl: component.contextUrl,\n ...(component.aiPrompt ? { aiPrompt: component.aiPrompt } : {}),\n ...(md ? { markdown: md } : {}),\n })\n } catch (e) {\n return error(`Context bundle unavailable: ${e instanceof Error ? e.message : String(e)}`)\n }\n },\n )\n\n server.registerTool(\n 'select_component',\n {\n title: 'Select component',\n description:\n 'Heuristic ranking of cascade components by natural language need. Returns top matches with scores and reasons. Note: heuristic ranking, not a model call.',\n inputSchema: {\n need: z.string().describe('Natural language description of what the component should do'),\n },\n },\n async ({ need }) => {\n try {\n const ctx = await loadContext(fetchFn)\n const results = selectComponent(need, ctx.components)\n return json({\n note: 'Heuristic ranking — not a model call. Verify with get_context before using.',\n results,\n })\n } catch (e) {\n return error(`Context bundle unavailable: ${e instanceof Error ? e.message : String(e)}`)\n }\n },\n )\n\n return server\n}\n","import { argv } from 'node:process'\nimport { pathToFileURL } from 'node:url'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { createServer } from './server.js'\n\nexport const VERSION = '0.0.0'\n\nexport { createServer } from './server.js'\nexport type { ServerOptions } from './server.js'\nexport { generateThemeCss, type ThemeColors } from './theme.js'\nexport { scaffoldPage, type ScaffoldOptions } from './scaffold.js'\nexport {\n buildGrammar,\n formatGrammar,\n parseEnum,\n type GrammarComponent,\n type GrammarProp,\n type ViewGrammar,\n} from './grammar.js'\nexport { buildGenerationPrompt, type GenerationPromptOptions } from './prompt.js'\nexport {\n getComponent,\n listComponents,\n loadRegistry,\n searchComponents,\n type ComponentManifest,\n type Registry,\n type RegistryComponent,\n} from './registry.js'\n\n/** Start the MCP server over stdio. */\nexport async function main(): Promise<void> {\n const server = createServer({ version: VERSION })\n await server.connect(new StdioServerTransport())\n}\n\nconst isMain = argv[1] !== undefined && import.meta.url === pathToFileURL(argv[1]).href\n\nif (isMain) {\n main().catch((err: unknown) => {\n console.error(err instanceof Error ? err.message : String(err))\n process.exitCode = 1\n })\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": "0.0.0",
3
- "generatedAt": "2026-06-23",
3
+ "generatedAt": "2026-06-25",
4
4
  "components": [
5
5
  {
6
6
  "name": "accordion",
@@ -17491,7 +17491,8 @@
17491
17491
  {
17492
17492
  "name": "series",
17493
17493
  "type": "BarChartSeries<Datum>[]",
17494
- "required": true
17494
+ "required": true,
17495
+ "description": "Series array. Each series accepts an optional `color` (any CSS color) overriding the positional palette for that series/stacked layer."
17495
17496
  },
17496
17497
  {
17497
17498
  "name": "x",
@@ -17547,11 +17548,28 @@
17547
17548
  "required": false,
17548
17549
  "default": "5"
17549
17550
  },
17551
+ {
17552
+ "name": "xLabelEvery",
17553
+ "type": "number",
17554
+ "required": false,
17555
+ "description": "Show every Nth category label (always the last) to thin a crowded x-axis."
17556
+ },
17550
17557
  {
17551
17558
  "name": "legend",
17552
17559
  "type": "boolean",
17553
17560
  "required": false
17554
17561
  },
17562
+ {
17563
+ "name": "tooltip",
17564
+ "type": "boolean",
17565
+ "required": false
17566
+ },
17567
+ {
17568
+ "name": "tooltipFormat",
17569
+ "type": "(p: ChartPoint) => string",
17570
+ "required": false,
17571
+ "description": "Custom tooltip formatter. The stacked default lists \"label · total\" + each non-zero layer in its color."
17572
+ },
17555
17573
  {
17556
17574
  "name": "className",
17557
17575
  "type": "string",
@@ -17565,6 +17583,108 @@
17565
17583
  "description": "Marks only — no axes, grid lines, or legend. For micro/inline charts."
17566
17584
  }
17567
17585
  ],
17586
+ "typeDefs": [
17587
+ {
17588
+ "name": "BarChartSeries<Datum>",
17589
+ "description": "One series (a set of bars). Pass an array via the `series` prop.",
17590
+ "fields": [
17591
+ {
17592
+ "name": "id",
17593
+ "type": "string",
17594
+ "required": true,
17595
+ "description": "Stable series identity."
17596
+ },
17597
+ {
17598
+ "name": "label",
17599
+ "type": "string",
17600
+ "required": true,
17601
+ "description": "Legend + tooltip label."
17602
+ },
17603
+ {
17604
+ "name": "data",
17605
+ "type": "readonly Datum[]",
17606
+ "required": true,
17607
+ "description": "Row data read by the `x`/`y` accessors."
17608
+ },
17609
+ {
17610
+ "name": "color",
17611
+ "type": "string",
17612
+ "required": false,
17613
+ "description": "Any CSS color overriding the positional palette (--cascivo-chart-N) for this series / stacked layer."
17614
+ }
17615
+ ]
17616
+ },
17617
+ {
17618
+ "name": "StackedRow",
17619
+ "description": "Row-oriented input to the `toStackedSeries(rows)` pivot helper.",
17620
+ "fields": [
17621
+ {
17622
+ "name": "label",
17623
+ "type": "string",
17624
+ "required": true,
17625
+ "description": "Category (one bar)."
17626
+ },
17627
+ {
17628
+ "name": "segments",
17629
+ "type": "StackedSegment[]",
17630
+ "required": true,
17631
+ "description": "Per-layer values: { key, value, color? }. First non-undefined color per key wins."
17632
+ }
17633
+ ]
17634
+ },
17635
+ {
17636
+ "name": "StackedSegment",
17637
+ "description": "One layer of a stacked bar within a StackedRow.",
17638
+ "fields": [
17639
+ {
17640
+ "name": "key",
17641
+ "type": "string",
17642
+ "required": true,
17643
+ "description": "Layer key — becomes the series id/label (e.g. \"Done\")."
17644
+ },
17645
+ {
17646
+ "name": "value",
17647
+ "type": "number",
17648
+ "required": true
17649
+ },
17650
+ {
17651
+ "name": "color",
17652
+ "type": "string",
17653
+ "required": false,
17654
+ "description": "Optional CSS color for this layer."
17655
+ }
17656
+ ]
17657
+ },
17658
+ {
17659
+ "name": "ChartPoint",
17660
+ "description": "Argument passed to the `tooltipFormat` callback.",
17661
+ "fields": [
17662
+ {
17663
+ "name": "label",
17664
+ "type": "string",
17665
+ "required": true,
17666
+ "description": "Category label."
17667
+ },
17668
+ {
17669
+ "name": "value",
17670
+ "type": "number | string",
17671
+ "required": true
17672
+ },
17673
+ {
17674
+ "name": "color",
17675
+ "type": "string",
17676
+ "required": false,
17677
+ "description": "Resolved mark color (the default tooltip tints its text with this)."
17678
+ },
17679
+ {
17680
+ "name": "segments",
17681
+ "type": "readonly { label: string; value: number; color?: string }[]",
17682
+ "required": false,
17683
+ "description": "Per-layer breakdown for a stacked category; the default stacked tooltip lists these."
17684
+ }
17685
+ ]
17686
+ }
17687
+ ],
17568
17688
  "tokens": [
17569
17689
  "--cascivo-chart-1",
17570
17690
  "--cascivo-chart-2",
@@ -17584,6 +17704,10 @@
17584
17704
  {
17585
17705
  "title": "Basic bar chart",
17586
17706
  "code": "import { BarChart } from '@cascivo/charts'\n\nconst series = [{ id: 'a', label: 'Sales', data: [{x:'Jan',y:100},{x:'Feb',y:150}] }]\n<BarChart series={series} x={d => d.x} y={d => d.y} title=\"Sales\" />"
17707
+ },
17708
+ {
17709
+ "title": "Stacked bar from row-oriented data",
17710
+ "code": "import { BarChart, toStackedSeries } from '@cascivo/charts'\n\n// Pivot { label, segments[] } rows into series + x/y. Per-segment color is preserved.\nconst rows = [\n { label: 'Mon', segments: [\n { key: 'Done', value: 5, color: 'var(--cascivo-color-success)' },\n { key: 'Blocked', value: 2, color: 'var(--cascivo-color-destructive)' },\n ] },\n { label: 'Tue', segments: [\n { key: 'Done', value: 8, color: 'var(--cascivo-color-success)' },\n { key: 'Blocked', value: 1, color: 'var(--cascivo-color-destructive)' },\n ] },\n]\n// Tooltip shows \"Mon · 7\" then each non-zero layer in its color.\n<BarChart mode=\"stacked\" tooltip {...toStackedSeries(rows)} title=\"Throughput\" />"
17587
17711
  }
17588
17712
  ],
17589
17713
  "dependencies": ["@cascivo/charts"],
@@ -18675,7 +18799,7 @@
18675
18799
  "name": "data",
18676
18800
  "type": "PieChartDatum[]",
18677
18801
  "required": true,
18678
- "description": "Array of { label, value } datums"
18802
+ "description": "Array of { id, label, value, color? } datums. Optional per-datum `color` (any CSS color) overrides the positional palette for that slice."
18679
18803
  },
18680
18804
  {
18681
18805
  "name": "title",
@@ -18704,6 +18828,54 @@
18704
18828
  "required": false,
18705
18829
  "default": "300"
18706
18830
  },
18831
+ {
18832
+ "name": "size",
18833
+ "type": "number",
18834
+ "required": false,
18835
+ "description": "Square shorthand: sets width === height. Explicit width/height win."
18836
+ },
18837
+ {
18838
+ "name": "thickness",
18839
+ "type": "number",
18840
+ "required": false,
18841
+ "description": "Ring width in px (donut only); defaults to 0.4 × radius."
18842
+ },
18843
+ {
18844
+ "name": "innerRadius",
18845
+ "type": "number",
18846
+ "required": false,
18847
+ "description": "Inner radius in px (donut only); takes precedence over thickness; clamped to [0, outerRadius)."
18848
+ },
18849
+ {
18850
+ "name": "centerValue",
18851
+ "type": "string",
18852
+ "required": false,
18853
+ "description": "Center value text rendered in the donut hole (donut only)."
18854
+ },
18855
+ {
18856
+ "name": "centerLabel",
18857
+ "type": "string",
18858
+ "required": false,
18859
+ "description": "Center label text rendered below the value (donut only)."
18860
+ },
18861
+ {
18862
+ "name": "centerSlot",
18863
+ "type": "ReactNode",
18864
+ "required": false,
18865
+ "description": "Arbitrary content for the donut hole; takes precedence over centerValue/centerLabel."
18866
+ },
18867
+ {
18868
+ "name": "emptyLabel",
18869
+ "type": "string",
18870
+ "required": false,
18871
+ "description": "Visible placeholder text when data is empty. Defaults to the i18n \"No data\"."
18872
+ },
18873
+ {
18874
+ "name": "tooltipFormat",
18875
+ "type": "(p: ChartPoint) => string",
18876
+ "required": false,
18877
+ "description": "Custom tooltip formatter. Defaults to \"value (pct%)\" in the slice color."
18878
+ },
18707
18879
  {
18708
18880
  "name": "legend",
18709
18881
  "type": "boolean",
@@ -18722,6 +18894,65 @@
18722
18894
  "description": "Marks only — no axes, grid lines, or legend. For micro/inline charts."
18723
18895
  }
18724
18896
  ],
18897
+ "typeDefs": [
18898
+ {
18899
+ "name": "PieChartDatum",
18900
+ "description": "One slice. Pass via the `data` prop.",
18901
+ "fields": [
18902
+ {
18903
+ "name": "id",
18904
+ "type": "string",
18905
+ "required": false,
18906
+ "description": "Stable identity (used for legend toggle state)."
18907
+ },
18908
+ {
18909
+ "name": "label",
18910
+ "type": "string",
18911
+ "required": true
18912
+ },
18913
+ {
18914
+ "name": "value",
18915
+ "type": "number",
18916
+ "required": true
18917
+ },
18918
+ {
18919
+ "name": "color",
18920
+ "type": "string",
18921
+ "required": false,
18922
+ "description": "Any CSS color overriding the positional palette (--cascivo-chart-N) for this slice."
18923
+ }
18924
+ ]
18925
+ },
18926
+ {
18927
+ "name": "ChartPoint",
18928
+ "description": "Argument passed to the `tooltipFormat` callback.",
18929
+ "fields": [
18930
+ {
18931
+ "name": "label",
18932
+ "type": "string",
18933
+ "required": true,
18934
+ "description": "Slice label."
18935
+ },
18936
+ {
18937
+ "name": "value",
18938
+ "type": "number | string",
18939
+ "required": true
18940
+ },
18941
+ {
18942
+ "name": "percent",
18943
+ "type": "number",
18944
+ "required": false,
18945
+ "description": "Share of the whole, 0–100. Used by the default \"value (pct%)\" formatter."
18946
+ },
18947
+ {
18948
+ "name": "color",
18949
+ "type": "string",
18950
+ "required": false,
18951
+ "description": "Resolved slice color (the default tooltip tints its text with this)."
18952
+ }
18953
+ ]
18954
+ }
18955
+ ],
18725
18956
  "tokens": [
18726
18957
  "--cascivo-chart-1",
18727
18958
  "--cascivo-chart-2",
@@ -18741,6 +18972,14 @@
18741
18972
  {
18742
18973
  "title": "Basic pie chart",
18743
18974
  "code": "import { PieChart } from '@cascivo/charts'\n\n<PieChart data={[{label:'A',value:60},{label:'B',value:40}]} title=\"Market share\" />"
18975
+ },
18976
+ {
18977
+ "title": "Donut with center total and custom thickness",
18978
+ "code": "import { PieChart } from '@cascivo/charts'\n\n<PieChart\n donut\n size={220}\n thickness={28}\n centerValue=\"142\"\n centerLabel=\"Total tasks\"\n data={[\n { id: 'done', label: 'Done', value: 92, color: 'var(--cascivo-color-success)' },\n { id: 'wip', label: 'In progress', value: 34, color: 'var(--cascivo-color-warning)' },\n { id: 'blocked', label: 'Blocked', value: 16, color: 'var(--cascivo-color-destructive)' },\n ]}\n title=\"Task status\"\n/>"
18979
+ },
18980
+ {
18981
+ "title": "Percentage tooltip + empty state",
18982
+ "code": "import { PieChart } from '@cascivo/charts'\n\n// Default tooltip shows \"value (pct%)\" in the slice color; pass tooltipFormat to override.\n<PieChart data={[{id:'a',label:'A',value:60},{id:'b',label:'B',value:40}]} title=\"Share\" />\n\n// Empty data renders a visible \"No data\" placeholder (override via emptyLabel).\n<PieChart data={[]} title=\"Share\" emptyLabel=\"Nothing tracked yet\" />"
18744
18983
  }
18745
18984
  ],
18746
18985
  "dependencies": ["@cascivo/charts"],
@@ -19233,6 +19472,341 @@
19233
19472
  },
19234
19473
  "install": "@cascivo/charts"
19235
19474
  },
19475
+ {
19476
+ "name": "editor/code-editor",
19477
+ "type": "editor",
19478
+ "description": "Lightweight code editor — a native textarea overlaid on a syntax-highlighted layer, with line numbers and Tab indent.",
19479
+ "category": "inputs",
19480
+ "version": "0.0.0",
19481
+ "files": [],
19482
+ "dependencies": ["@cascivo/core", "@cascivo/i18n"],
19483
+ "tags": ["editor", "code", "syntax-highlighting", "textarea", "inputs"],
19484
+ "meta": {
19485
+ "name": "CodeEditor",
19486
+ "description": "Lightweight code editor — a native textarea overlaid on a syntax-highlighted layer, with line numbers and Tab indent.",
19487
+ "category": "inputs",
19488
+ "states": ["default"],
19489
+ "variants": [],
19490
+ "sizes": [],
19491
+ "props": [
19492
+ {
19493
+ "name": "value",
19494
+ "type": "string",
19495
+ "required": false,
19496
+ "description": "Controlled value"
19497
+ },
19498
+ {
19499
+ "name": "defaultValue",
19500
+ "type": "string",
19501
+ "required": false,
19502
+ "description": "Initial value for uncontrolled use"
19503
+ },
19504
+ {
19505
+ "name": "onValueChange",
19506
+ "type": "(value: string) => void",
19507
+ "required": false,
19508
+ "description": "Called with the new text on every edit"
19509
+ },
19510
+ {
19511
+ "name": "language",
19512
+ "type": "string",
19513
+ "required": false,
19514
+ "default": "plaintext",
19515
+ "description": "Grammar name (plaintext/json/javascript/typescript/css/html/markdown/bash)"
19516
+ },
19517
+ {
19518
+ "name": "lineNumbers",
19519
+ "type": "boolean",
19520
+ "required": false,
19521
+ "default": "true",
19522
+ "description": "Show the line-number gutter"
19523
+ },
19524
+ {
19525
+ "name": "tabSize",
19526
+ "type": "number",
19527
+ "required": false,
19528
+ "default": "2",
19529
+ "description": "Spaces per tab stop"
19530
+ },
19531
+ {
19532
+ "name": "insertSpaces",
19533
+ "type": "boolean",
19534
+ "required": false,
19535
+ "default": "true",
19536
+ "description": "Insert spaces vs a literal tab on Tab"
19537
+ },
19538
+ {
19539
+ "name": "wrap",
19540
+ "type": "boolean",
19541
+ "required": false,
19542
+ "default": "false",
19543
+ "description": "Soft-wrap long lines instead of scrolling horizontally"
19544
+ },
19545
+ {
19546
+ "name": "readOnly",
19547
+ "type": "boolean",
19548
+ "required": false,
19549
+ "default": "false"
19550
+ },
19551
+ {
19552
+ "name": "disabled",
19553
+ "type": "boolean",
19554
+ "required": false,
19555
+ "default": "false"
19556
+ },
19557
+ {
19558
+ "name": "placeholder",
19559
+ "type": "string",
19560
+ "required": false
19561
+ },
19562
+ {
19563
+ "name": "label",
19564
+ "type": "string",
19565
+ "required": false,
19566
+ "description": "Accessible label (defaults to the i18n \"Code editor\")"
19567
+ },
19568
+ {
19569
+ "name": "onSave",
19570
+ "type": "(value: string) => void",
19571
+ "required": false,
19572
+ "description": "Called on Mod-S; the browser save dialog is suppressed"
19573
+ },
19574
+ {
19575
+ "name": "bracketMatching",
19576
+ "type": "boolean",
19577
+ "required": false,
19578
+ "default": "false",
19579
+ "description": "Highlight the bracket matching the one adjacent to the caret"
19580
+ },
19581
+ {
19582
+ "name": "theme",
19583
+ "type": "EditorTheme",
19584
+ "required": false,
19585
+ "description": "Per-instance --cascivo-editor-* overrides; swapping it re-themes live"
19586
+ },
19587
+ {
19588
+ "name": "keymap",
19589
+ "type": "KeyMap",
19590
+ "required": false,
19591
+ "description": "Extra key bindings merged over the built-ins (user wins on a chord)"
19592
+ },
19593
+ {
19594
+ "name": "decorations",
19595
+ "type": "Decoration[] | ((value: string) => Decoration[])",
19596
+ "required": false,
19597
+ "description": "Extra offset-range → CSS class decorations"
19598
+ },
19599
+ {
19600
+ "name": "ref",
19601
+ "type": "Ref<CodeEditorHandle>",
19602
+ "required": false,
19603
+ "description": "Imperative handle: applyEdit / getSelection / focus / undo / redo / openFind"
19604
+ },
19605
+ {
19606
+ "name": "className",
19607
+ "type": "string",
19608
+ "required": false
19609
+ }
19610
+ ],
19611
+ "tokens": [
19612
+ "--cascivo-editor-bg",
19613
+ "--cascivo-editor-fg",
19614
+ "--cascivo-editor-gutter-bg",
19615
+ "--cascivo-editor-gutter-fg",
19616
+ "--cascivo-editor-gutter-active",
19617
+ "--cascivo-editor-current-line",
19618
+ "--cascivo-editor-selection",
19619
+ "--cascivo-editor-border",
19620
+ "--cascivo-editor-match",
19621
+ "--cascivo-editor-match-current",
19622
+ "--cascivo-editor-bracket"
19623
+ ],
19624
+ "accessibility": {
19625
+ "role": "textbox",
19626
+ "wcag": "2.1-AA",
19627
+ "keyboard": [
19628
+ "Tab (indent)",
19629
+ "Shift+Tab (dedent)",
19630
+ "Mod+Z / Mod+Shift+Z (undo / redo)",
19631
+ "Mod+F (find)",
19632
+ "Mod+Alt+F (replace)",
19633
+ "Mod+S (save)",
19634
+ "Standard textarea editing"
19635
+ ],
19636
+ "reducedMotion": true,
19637
+ "forcedColors": true
19638
+ },
19639
+ "examples": [
19640
+ {
19641
+ "title": "Basic editor",
19642
+ "code": "import { CodeEditor } from '@cascivo/editor'\nimport '@cascivo/editor/styles.css'\n\n<CodeEditor language=\"typescript\" lineNumbers defaultValue={'const x = 1\\n'} />"
19643
+ },
19644
+ {
19645
+ "title": "Controlled",
19646
+ "code": "<CodeEditor language=\"json\" value={value} onValueChange={setValue} />"
19647
+ },
19648
+ {
19649
+ "title": "Notes editing — find, save, brackets",
19650
+ "code": "<CodeEditor\n language=\"markdown\"\n value={doc}\n onValueChange={setDoc}\n onSave={save} // Mod-S\n bracketMatching\n/> // Mod-F to search"
19651
+ }
19652
+ ],
19653
+ "dependencies": ["@cascivo/core", "@cascivo/i18n"],
19654
+ "tags": ["editor", "code", "syntax-highlighting", "textarea", "inputs"],
19655
+ "intent": {
19656
+ "whenToUse": [
19657
+ "Editing code or config inline — JSON, snippets, web languages — with line numbers and syntax colors",
19658
+ "A lightweight, themeable code field where a full IDE editor (Monaco/CodeMirror) would be overkill",
19659
+ "Editing Markdown notes — find/replace, real undo/redo, save, and selection-preserving external sync",
19660
+ "Editing long-form Markdown — generated docs, concatenated books, big notes — windowed (viewport-scoped) tokenization keeps scrolling/typing smooth well past ~5,000 lines"
19661
+ ],
19662
+ "whenNotToUse": [
19663
+ "You need IntelliSense/LSP, multi-cursor, folding, a minimap, or diff view — use a full editor framework",
19664
+ "Plain prose or a single-line value — use Textarea or Input",
19665
+ "Sustained editing of 100k+-line documents — use a full editor framework / dedicated worker pipeline (the windowed tokenizer keeps per-render work O(viewport), but a worker offload is intentionally out of scope)",
19666
+ "Soft-wrap (wrap) on a very large document — rendering is O(n) under wrap; disable wrap above ~10k lines for sustained editing"
19667
+ ],
19668
+ "antiPatterns": [
19669
+ {
19670
+ "bad": "Reaching for Monaco to show an editable snippet",
19671
+ "good": "Use CodeEditor for the basic set (line numbers + highlighting) at a fraction of the weight",
19672
+ "why": "The overlay technique keeps the bundle tiny and themes via the cascivo token system"
19673
+ }
19674
+ ],
19675
+ "related": [
19676
+ {
19677
+ "name": "Highlight",
19678
+ "relationship": "pairs-with",
19679
+ "reason": "The read-only renderer sharing the same tokenizer — for snippets and docs"
19680
+ },
19681
+ {
19682
+ "name": "Textarea",
19683
+ "relationship": "alternative",
19684
+ "reason": "Use for free-form prose without syntax highlighting"
19685
+ }
19686
+ ],
19687
+ "a11yRationale": "The native <textarea> is the editing surface, so caret, selection, IME, undo, and the a11y tree come from the browser; the highlight layer and gutter are aria-hidden.",
19688
+ "flexibility": [
19689
+ {
19690
+ "area": "languages",
19691
+ "level": "flexible",
19692
+ "note": "Ships a small grammar set; registerGrammar adds custom languages without bundle bloat"
19693
+ },
19694
+ {
19695
+ "area": "large documents",
19696
+ "level": "flexible",
19697
+ "note": "Windowed tokenization (tokenizeRange + LineStateIndex) makes per-render work O(viewport) and per-edit work O(changed suffix); long Markdown edits well past ~5,000 lines. Worker offload / 100k+-line sustained editing stay out of scope"
19698
+ }
19699
+ ]
19700
+ }
19701
+ },
19702
+ "install": "@cascivo/editor"
19703
+ },
19704
+ {
19705
+ "name": "editor/highlight",
19706
+ "type": "editor",
19707
+ "description": "Read-only syntax-highlighted code block — the same owned tokenizer as CodeEditor, without the textarea.",
19708
+ "category": "display",
19709
+ "version": "0.0.0",
19710
+ "files": [],
19711
+ "dependencies": ["@cascivo/core", "@cascivo/i18n"],
19712
+ "tags": ["editor", "code", "syntax-highlighting", "display", "read-only"],
19713
+ "meta": {
19714
+ "name": "Highlight",
19715
+ "description": "Read-only syntax-highlighted code block — the same owned tokenizer as CodeEditor, without the textarea.",
19716
+ "category": "display",
19717
+ "states": [],
19718
+ "variants": [],
19719
+ "sizes": [],
19720
+ "props": [
19721
+ {
19722
+ "name": "value",
19723
+ "type": "string",
19724
+ "required": true,
19725
+ "description": "Code to render"
19726
+ },
19727
+ {
19728
+ "name": "language",
19729
+ "type": "string",
19730
+ "required": false,
19731
+ "default": "plaintext",
19732
+ "description": "Grammar name (plaintext/json/javascript/typescript/css/html/markdown/bash)"
19733
+ },
19734
+ {
19735
+ "name": "lineNumbers",
19736
+ "type": "boolean",
19737
+ "required": false,
19738
+ "default": "false",
19739
+ "description": "Show the line-number gutter"
19740
+ },
19741
+ {
19742
+ "name": "wrap",
19743
+ "type": "boolean",
19744
+ "required": false,
19745
+ "default": "false",
19746
+ "description": "Soft-wrap long lines"
19747
+ },
19748
+ {
19749
+ "name": "tabSize",
19750
+ "type": "number",
19751
+ "required": false,
19752
+ "default": "2",
19753
+ "description": "Spaces per tab stop"
19754
+ },
19755
+ {
19756
+ "name": "label",
19757
+ "type": "string",
19758
+ "required": false,
19759
+ "description": "Accessible label for the code block"
19760
+ },
19761
+ {
19762
+ "name": "className",
19763
+ "type": "string",
19764
+ "required": false
19765
+ }
19766
+ ],
19767
+ "tokens": [
19768
+ "--cascivo-editor-bg",
19769
+ "--cascivo-editor-fg",
19770
+ "--cascivo-editor-gutter-bg",
19771
+ "--cascivo-editor-gutter-fg",
19772
+ "--cascivo-editor-border"
19773
+ ],
19774
+ "accessibility": {
19775
+ "role": "group",
19776
+ "wcag": "2.1-AA",
19777
+ "keyboard": ["Scroll (no interactive controls)"]
19778
+ },
19779
+ "examples": [
19780
+ {
19781
+ "title": "Read-only snippet",
19782
+ "code": "import { Highlight } from '@cascivo/editor'\nimport '@cascivo/editor/styles.css'\n\n<Highlight language=\"json\" value={'{ \"ok\": true }'} />"
19783
+ }
19784
+ ],
19785
+ "dependencies": ["@cascivo/core", "@cascivo/i18n"],
19786
+ "tags": ["editor", "code", "syntax-highlighting", "display", "read-only"],
19787
+ "intent": {
19788
+ "whenToUse": [
19789
+ "Displaying non-editable code or config with syntax colors — docs, snippets, examples",
19790
+ "A lightweight highlighter that themes via the cascivo token system"
19791
+ ],
19792
+ "whenNotToUse": [
19793
+ "The code must be editable — use CodeEditor",
19794
+ "You need copy-to-clipboard chrome around a snippet — pair with a code-snippet surface"
19795
+ ],
19796
+ "antiPatterns": [],
19797
+ "related": [
19798
+ {
19799
+ "name": "CodeEditor",
19800
+ "relationship": "pairs-with",
19801
+ "reason": "The editable surface sharing the same tokenizer"
19802
+ }
19803
+ ],
19804
+ "a11yRationale": "Renders a read-only <pre><code>; the line-number gutter is aria-hidden and an optional label names the block.",
19805
+ "flexibility": []
19806
+ }
19807
+ },
19808
+ "install": "@cascivo/editor"
19809
+ },
19236
19810
  {
19237
19811
  "name": "section/cta",
19238
19812
  "type": "section",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cascivo/mcp",
3
- "version": "0.1.5",
3
+ "version": "0.1.8",
4
4
  "private": false,
5
5
  "description": "MCP server exposing the cascivo component registry to AI agents",
6
6
  "keywords": [