export declare const skillTemplate = "---\nname: ont-run\ndescription: Reference for ont-run API configuration and patterns. Use when modifying ontology.config.ts, creating resolvers, or working with the Vanna Design System.\n---\n\n# ont-run Reference\n\n## ontology.config.ts Configuration\n\nThis example demonstrates ALL configuration features:\n\n```typescript\nimport { defineOntology, userContext, organizationContext, fieldFrom } from 'ont-run';\nimport { z } from 'zod';\n\n// Import resolver functions\nimport healthCheck from './resolvers/healthCheck.js';\nimport getUser from './resolvers/getUser.js';\nimport editPost from './resolvers/editPost.js';\nimport createProject from './resolvers/createProject.js';\nimport getUserStatuses from './resolvers/options/userStatuses.js';\nimport searchTeams from './resolvers/options/searchTeams.js';\nimport createUser from './resolvers/createUser.js';\n\nexport default defineOntology({\n name: 'example-api',\n\n // Environment-specific configuration\n environments: {\n dev: { debug: true, apiUrl: 'http://localhost:3000' },\n prod: { debug: false, apiUrl: 'https://api.example.com' },\n },\n\n // Pluggable auth - returns AuthResult with groups + optional user/organization\n auth: async (req) => {\n const token = req.headers.get('Authorization');\n\n if (!token) {\n return { groups: ['public'] };\n }\n\n // Verify token and get user (your auth logic here)\n const user = await verifyToken(token);\n\n // For multi-tenant apps, extract organization context\n const orgId = new URL(req.url).searchParams.get('org_id');\n if (orgId) {\n // Verify user's membership in the organization\n const org = await db.organizations.findById(orgId);\n const isMember = await db.organizationMembers.exists({ userId: user.id, orgId });\n \n if (isMember) {\n return {\n groups: user.isAdmin ? ['admin', 'member'] : ['member'],\n user: { id: user.id, email: user.email }, // For userContext()\n organization: { id: org.id, name: org.name }, // For organizationContext()\n };\n }\n }\n\n return {\n groups: user.isAdmin ? ['admin', 'user', 'public'] : ['user', 'public'],\n user: { id: user.id, email: user.email }, // For userContext()\n };\n },\n\n // Define access groups with descriptions\n accessGroups: {\n public: { description: 'Unauthenticated users' },\n user: { description: 'Authenticated users' },\n member: { description: 'Organization members' },\n admin: { description: 'Administrators' },\n },\n\n // Define entities for categorization\n entities: {\n User: { description: 'A user account' },\n Post: { description: 'A blog post' },\n Team: { description: 'A team/organization' },\n },\n\n functions: {\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n // Basic function (inputs only, no outputs schema)\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n healthCheck: {\n description: 'Check API health status',\n access: ['public', 'user', 'admin'],\n entities: [],\n inputs: z.object({}),\n resolver: healthCheck,\n },\n\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n // Function with outputs schema (recommended for documentation)\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n getUser: {\n description: 'Get user by ID',\n access: ['user', 'admin'],\n entities: ['User'],\n inputs: z.object({\n userId: z.string().uuid(),\n }),\n outputs: z.object({\n id: z.string(),\n name: z.string(),\n email: z.string(),\n createdAt: z.string(),\n }),\n resolver: getUser,\n },\n\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n // Function with userContext() for row-level access control\n // The currentUser field is injected from auth() and hidden from API\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n editPost: {\n description: 'Edit a post (users can only edit their own posts)',\n access: ['user', 'admin'],\n entities: ['Post'],\n inputs: z.object({\n postId: z.string(),\n title: z.string(),\n content: z.string(),\n // userContext() marks this field as:\n // - Injected from auth() result's user field\n // - Hidden from public API/MCP schemas\n // - Type-safe in resolver\n currentUser: userContext(z.object({\n id: z.string(),\n email: z.string(),\n })),\n }),\n resolver: editPost,\n },\n\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n // Function with organizationContext() for multi-tenant access control\n // The currentOrg field is injected from auth() and hidden from API\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n createProject: {\n description: 'Create a project in the organization',\n access: ['member'],\n entities: ['Project'],\n inputs: z.object({\n name: z.string(),\n description: z.string().optional(),\n // organizationContext() marks this field as:\n // - Injected from auth() result's organization field\n // - Hidden from public API/MCP schemas\n // - Type-safe in resolver\n currentOrg: organizationContext(z.object({\n id: z.string(),\n name: z.string(),\n })),\n }),\n resolver: createProject,\n },\n\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n // Bulk options source for fieldFrom()\n // Empty inputs = all options fetched at once (dropdown)\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n getUserStatuses: {\n description: 'Get available user statuses',\n access: ['admin'],\n entities: [],\n inputs: z.object({}),\n outputs: z.array(z.object({\n value: z.string(),\n label: z.string(),\n })),\n resolver: getUserStatuses,\n },\n\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n // Autocomplete options source for fieldFrom()\n // Has query input = options searched dynamically (autocomplete)\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n searchTeams: {\n description: 'Search teams by name',\n access: ['admin'],\n entities: ['Team'],\n inputs: z.object({\n query: z.string(),\n }),\n outputs: z.array(z.object({\n value: z.string(),\n label: z.string(),\n })),\n resolver: searchTeams,\n },\n\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n // Function using fieldFrom() for dynamic options\n // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n createUser: {\n description: 'Create a new user',\n access: ['admin'],\n entities: ['User'],\n inputs: z.object({\n name: z.string(),\n email: z.string().email(),\n // fieldFrom() references another function for options:\n // - Bulk: getUserStatuses has empty inputs \u2192 dropdown\n // - Autocomplete: searchTeams has query input \u2192 search\n status: fieldFrom('getUserStatuses'),\n team: fieldFrom('searchTeams'),\n }),\n resolver: createUser,\n },\n },\n});\n```\n\n## ResolverContext\n\nEvery resolver receives a `ResolverContext` as its first argument:\n\n```typescript\nimport type { ResolverContext } from 'ont-run';\n\nexport default async function myResolver(ctx: ResolverContext, args: MyArgs) {\n // ctx.env - Current environment name ('dev', 'prod', etc.)\n ctx.logger.info(`Running in ${ctx.env}`);\n\n // ctx.envConfig - Environment-specific configuration\n if (ctx.envConfig.debug) {\n ctx.logger.debug('Debug mode enabled');\n }\n\n // ctx.logger - Structured logging\n ctx.logger.info('Processing request');\n ctx.logger.warn('Something might be wrong');\n ctx.logger.error('Something went wrong');\n ctx.logger.debug('Detailed info');\n\n // ctx.accessGroups - Groups from auth() for this request\n if (ctx.accessGroups.includes('admin')) {\n // Admin-only logic\n }\n\n return { /* result */ };\n}\n```\n\n## Vanna Design System\n\n### Colors\n- **Navy** (#023d60) - Primary text and backgrounds\n- **Cream** (#e7e1cf) - Page background\n- **Teal** (#15a8a8) - Primary accent, buttons\n- **Orange** (#fe5d26) - Secondary accent\n- **Magenta** (#bf1363) - Alerts, negative trends\n\n### Typography\n- **Roboto Slab** - Headlines (serif)\n- **Space Grotesk** - Body text (sans)\n- **Space Mono** - Code blocks (mono)\n\n### Components\n- `VannaButton` - 4 variants (primary/secondary/outline/ghost), 3 sizes\n- `VannaCard` - Cards with teal shadows\n- `StatsCard` - Dashboard stat cards with trend indicators\n- `Layout` - Glass-morphism navigation with lucide icons\n\n## Project Structure\n\n```\nproject/\n\u251C\u2500\u2500 ontology.config.ts # API configuration\n\u251C\u2500\u2500 build.ts # Production build script\n\u251C\u2500\u2500 src/\n\u2502 \u251C\u2500\u2500 index.ts # Server entry point\n\u2502 \u251C\u2500\u2500 index.html # HTML template\n\u2502 \u251C\u2500\u2500 index.css # Vanna Design System (Tailwind)\n\u2502 \u251C\u2500\u2500 frontend.tsx # React entry point\n\u2502 \u251C\u2500\u2500 App.tsx # React app with routing\n\u2502 \u251C\u2500\u2500 components/ # Vanna UI components\n\u2502 \u2514\u2500\u2500 routes/ # Page components\n\u2514\u2500\u2500 resolvers/ # API resolver functions\n```\n";