{"owner":"graffle-js","repo":"graffle","hasSkills":true,"totalSkillsCount":2,"totalTokensCount":2656,"categories":["claude-rule","plugin-manifest"],"hasMcp":false,"mcpConfig":null,"found":["CLAUDE.md","tools/vitest-plugin-examples/README.md"],"skills":{"CLAUDE.md":"# Local Claude Rules for Graffle Project\n\n## CRITICAL: Generated Files\n\n**NEVER EDIT GENERATED FILES**\n\n- Any file in `__tests__/fixtures/*/modules/` directories is GENERATED\n- These files are created by generator scripts and should NEVER be manually edited\n- If there are issues with generated files, fix the generator code, not the generated output\n- Always regenerate fixtures using the appropriate pnpm scripts after fixing generators\n\nGenerated file patterns to NEVER edit:\n\n- `src/extensions/DocumentBuilder/__tests__/fixtures/*/modules/*.ts`\n- Any file that has been marked as generated or comes from a generator script\n\n## Type Assertion Formatting\n\nWhen using `Ts.Assert` in test files (`.test-d.ts`):\n\n1. **Use alias at module top**: `const A = Ts.Assert`\n2. **Single-line format** for short assertions:\n   ```typescript\n   A.exact.ofAs<string>().onAs<Type>()\n   ```\n3. **Multi-line format** when combined expected + actual types visually exceed ~50 characters:\n   ```typescript\n   A.sub.ofAs<LongExpectedType>()\n     .onAs<LongActualType>()\n   ```\n4. **Indentation rule**: Align the `.onAs` dot with the `.ofAs` dot\n   - Count characters in prefix (e.g., `A.sub.` = 5 chars)\n   - Use that many spaces before `.onAs`\n   - Examples:\n     - `A.exact.` → 7 spaces before `.onAs`\n     - `A.sub.` → 5 spaces before `.onAs`\n     - `A.equiv.` → 7 spaces before `.onAs`\n     - `A.awaited.exact.` → 15 spaces before `.onAs`\n","tools/vitest-plugin-examples/README.md":"# Vitest Examples Plugin\n\nA Vite plugin for testing executable documentation examples with type-safe configuration. This plugin automatically discovers example files, generates TypeScript types for type-safe encoder configuration, executes examples, captures their output, and integrates with Vitest's snapshot testing.\n\n## Features\n\n- **Automatic Type Generation**: Generates TypeScript types in `@generated/test-examples` for type-safe encoder configuration\n- **Automatic Discovery**: Finds example files using glob patterns\n- **Output Capture**: Executes examples and captures stdout/stderr using Effect Platform\n- **Dynamic Value Masking**: Type-safe encoder configuration for masking non-deterministic values\n- **Snapshot Testing**: Integrates seamlessly with Vitest inline snapshots\n- **Lifecycle Hooks**: Support for setup/teardown before/after each example\n- **Sequential Execution**: Runs examples sequentially to avoid race conditions\n- **IDE Autocomplete**: Full TypeScript autocomplete for example file paths\n- **Configurable Execution**: Customize executor command, cwd, and environment\n\n## Installation\n\n```bash\npnpm add -D @jasonkuhrt/vitest-plugin-examples\n```\n\nOr use it locally within the Graffle monorepo.\n\n## Usage\n\n### 1. Configure Vitest to Use the Plugin\n\nIn your `vitest.config.ts`:\n\n```typescript\nimport { examplesPlugin } from '@jasonkuhrt/vitest-plugin-examples'\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  plugins: [\n    examplesPlugin({\n      pattern: './*/*.ts',\n      outputDir: './__outputs__',\n    }),\n  ],\n  // ... rest of your config\n})\n```\n\nThe plugin runs during Vite's `buildStart` lifecycle, generating types before TypeScript compilation.\n\n### 2. Use the Convenience Test Function\n\nIn your test file:\n\n```typescript\nimport type { ExamplePath } from '@generated/test-examples'\nimport { createExamplesTest } from '@jasonkuhrt/vitest-plugin-examples'\nimport { test } from 'vitest'\n\n// Type-safe encoder configuration with autocomplete\nconst encoders = {\n  './examples/dynamic-timestamp.ts': (value: string) => {\n    return value.replace(/timestamp: \\d+/g, 'timestamp: MASKED')\n  },\n} satisfies Partial<Record<ExamplePath, EncoderFunction>>\n\ncreateExamplesTest(test, {\n  timeout: 300000,\n  config: {\n    pattern: './*/*.ts',\n    outputDir: './__outputs__',\n    ignore: ['./$', './__outputs__', './__tests__'],\n    encoders,\n    beforeEach: async () => {\n      // Reset database before each example\n      await db.reset()\n    },\n  },\n})\n```\n\nThat's it! The `createExamplesTest()` function:\n\n- Automatically runs all discovered examples\n- Creates a single Vitest test case\n- Generates individual snapshots for each example\n- Handles all assertions internally\n\n### Type-Safe Encoders\n\nThe plugin generates TypeScript types for all discovered example files in `node_modules/@generated/test-examples/`:\n\n```typescript\n// Auto-generated - provides autocomplete for example paths\nexport interface ExampleFiles {\n  './examples/example1.ts': true\n  './examples/example2.ts': true\n  // ... all discovered examples\n}\n\nexport type ExamplePath = keyof ExampleFiles\n```\n\nUse these types for type-safe encoder configuration:\n\n```typescript\nimport type { EncoderFunction, ExamplePath } from '@generated/test-examples'\n\nconst encoders = {\n  './examples/dynamic-values.ts': (output: string) => {\n    return output.replace(/'x-timestamp', '\\d+'/gi, `'x-timestamp', 'MASKED'`)\n  },\n  // ✅ TypeScript autocomplete works here!\n  // ✅ Typos are caught at compile time!\n} satisfies Partial<Record<ExamplePath, EncoderFunction>>\n```\n\n### Advanced: Manual Test Setup\n\nIf you need more control, you can use the lower-level APIs:\n\n```typescript\nimport { runExamples } from '@jasonkuhrt/vitest-plugin-examples'\nimport { expect, test } from 'vitest'\n\ntest('examples', async () => {\n  const results = await runExamples({\n    pattern: './*/*.ts',\n    outputDir: './__outputs__',\n  })\n\n  for (const result of results) {\n    expect(result.encoded).toMatchSnapshot(\n      `${result.file.group}/${result.file.name}`,\n    )\n  }\n}, { timeout: 300000 })\n```\n\n## Configuration\n\n### `ExamplesPluginConfig`\n\n```typescript\ninterface ExamplesPluginConfig {\n  /**\n   * Glob pattern(s) to discover example files.\n   * @default './examples/*\\/*.ts'\n   */\n  pattern?: string | string[]\n\n  /**\n   * Directory where output files will be written.\n   * @default './examples/__outputs__'\n   */\n  outputDir?: string\n\n  /**\n   * Patterns to ignore when discovering examples.\n   * @default ['./examples/$', './examples/__outputs__', './examples/__tests__']\n   */\n  ignore?: string[]\n\n  /**\n   * Custom encoder functions for masking dynamic values in outputs.\n   * Keys are example file paths (relative to project root).\n   */\n  encoders?: Record<string, EncoderFunction>\n\n  /**\n   * Hook called before each example is executed.\n   */\n  beforeEach?: () => Promise<void> | void\n\n  /**\n   * Hook called after each example is executed.\n   */\n  afterEach?: () => Promise<void> | void\n\n  /**\n   * Whether to apply dynamic value masking for test determinism.\n   * @default true\n   */\n  maskDynamicValues?: boolean\n\n  /**\n   * Execution configuration for running examples.\n   */\n  executor?: {\n    /**\n     * Command to execute examples.\n     * @default ['tsx']\n     */\n    command?: string[]\n    /**\n     * Working directory for command execution.\n     * @default process.cwd()\n     */\n    cwd?: string\n    /**\n     * Environment variables to pass to the command.\n     * @default process.env\n     */\n    env?: Record<string, string | undefined>\n  }\n\n  /**\n   * Type generation configuration.\n   */\n  typeGeneration?: {\n    /**\n     * Whether to enable type generation.\n     * @default true\n     */\n    enabled?: boolean\n    /**\n     * Output directory for generated types.\n     * @default 'node_modules/@generated/test-examples'\n     */\n    outputDir?: string\n    /**\n     * Package name for generated types.\n     * @default '@generated/test-examples'\n     */\n    packageName?: string\n  }\n}\n```\n\n### `ExampleResult`\n\n```typescript\ninterface ExampleResult {\n  /** The example file that was executed */\n  file: ExampleFile\n  /** Captured stdout output */\n  stdout: string\n  /** Captured stderr output */\n  stderr: string\n  /** Whether the example failed */\n  failed: boolean\n  /** Exit code from the process */\n  exitCode: number | null\n  /** Encoded output (after applying encoders and masking) */\n  encoded: string\n}\n```\n\n## How It Works\n\n1. **Type Generation** (Vite plugin, `buildStart` hook):\n   - Discovers example files using Kit's `Fs.glob()`\n   - Generates TypeScript types to `node_modules/@generated/test-examples/`\n   - Creates proper npm package with `package.json` for TypeScript module resolution\n   - Runs before TypeScript compilation, ensuring types are available during type checking\n\n2. **Test Execution** (Vitest runtime):\n   - Discovers example files matching the pattern\n   - Runs each example using Effect Platform's `Command` API (configurable executor)\n   - Captures stdout/stderr using Effect Streams\n   - Applies custom encoders + default masking for determinism\n   - Creates individual inline snapshots for each example\n\n### Default Encoding\n\nThe plugin applies default encoding to mask common dynamic values:\n\n- File paths → `/some/path/to/file.ts:XX:XX`\n- Node.js version → `Node.js vXX.XX.XX`\n- Node internal module line numbers\n- Dynamic error formatting differences\n\n## API\n\n### Plugin API\n\n#### `examplesPlugin(config?)`\n\nVite plugin that generates TypeScript types for example files during build.\n\n**Usage**: Add to `vitest.config.ts` plugins array\n\n**Configuration**: Same as `ExamplesPluginConfig`\n\n### Test Helper API\n\n#### `createExamplesTest(test, options?)`\n\nConvenience function that creates a complete test case for all examples.\n\n**Parameters**:\n\n- `test` - Vitest's `test` function\n- `options` - Configuration object:\n  - `config?: ExamplesPluginConfig` - Plugin configuration\n  - `timeout?: number` - Test timeout in milliseconds (default: 300000)\n  - `testName?: string` - Name of the test case (default: 'examples')\n\n**Returns**: void (creates test internally)\n\n#### `testExamples(config?)`\n\nCreates a function that runs all examples with the given configuration.\n\n**Returns**: `() => Promise<ExampleResult[]>`\n\n#### `runExamples(config)`\n\nRuns all examples and returns their results.\n\n**Returns**: `Promise<ExampleResult[]>`\n\n#### `runExample(relativePath, config)`\n\nRuns a single example by its relative path.\n\n**Returns**: `Promise<ExampleResult>`\n\n#### `discoverExamples(config)`\n\nDiscovers example files without executing them.\n\n**Returns**: `Promise<ExampleFile[]>`\n\n#### `captureExample(file, config)`\n\nExecutes a single example file and captures its output.\n\n**Returns**: `Promise<ExampleResult>`\n\n## Migration from Old System\n\nThe old system used:\n\n- `scripts/generate-examples-derivatives/generate-outputs.ts` - Manual output generation\n- Custom `runExample()` and `runExampleForTest()` functions\n- Separate snapshot path construction\n- Manual encoder loading\n\nThe new plugin simplifies this to:\n\n- Single `testExamples()` call\n- Automatic snapshot integration\n- Inline encoder configuration\n- No manual output file generation needed\n\n## Performance\n\n- Examples run **sequentially** (not in parallel) to prevent race conditions\n- Typical run time: ~2-5 minutes for ~30 examples\n- Set test timeout to at least 300000ms (5 minutes)\n\n## Dependencies\n\nThis plugin requires:\n\n- **Effect Platform** (`@effect/platform`, `@effect/platform-node`, `effect`) - For command execution and stream handling\n- **@wollybeard/kit** - For file system operations and FsLoc types\n- **Vite & Vitest** (peer dependencies)\n\n## Limitations\n\n- Executes examples via configurable executor (default: `tsx`)\n- Sequential execution means slower than parallel (by design, for safety)\n- Snapshot comparison happens in-memory (inline snapshots)\n- Generated types live in `node_modules/@generated/` - not committed to git\n- Requires Effect Platform and Kit dependencies\n\n## Future Improvements\n\n- Support for parallel execution with opt-in\n- Option to commit generated types to source control\n- Comparison utilities for validating against old system\n- Support for custom snapshot serializers\n- Lighter-weight alternative without Effect/Kit dependencies\n"},"files":{"CLAUDE.md":"# Local Claude Rules for Graffle Project\n\n## CRITICAL: Generated Files\n\n**NEVER EDIT GENERATED FILES**\n\n- Any file in `__tests__/fixtures/*/modules/` directories is GENERATED\n- These files are created by generator scripts and should NEVER be manually edited\n- If there are issues with generated files, fix the generator code, not the generated output\n- Always regenerate fixtures using the appropriate pnpm scripts after fixing generators\n\nGenerated file patterns to NEVER edit:\n\n- `src/extensions/DocumentBuilder/__tests__/fixtures/*/modules/*.ts`\n- Any file that has been marked as generated or comes from a generator script\n\n## Type Assertion Formatting\n\nWhen using `Ts.Assert` in test files (`.test-d.ts`):\n\n1. **Use alias at module top**: `const A = Ts.Assert`\n2. **Single-line format** for short assertions:\n   ```typescript\n   A.exact.ofAs<string>().onAs<Type>()\n   ```\n3. **Multi-line format** when combined expected + actual types visually exceed ~50 characters:\n   ```typescript\n   A.sub.ofAs<LongExpectedType>()\n     .onAs<LongActualType>()\n   ```\n4. **Indentation rule**: Align the `.onAs` dot with the `.ofAs` dot\n   - Count characters in prefix (e.g., `A.sub.` = 5 chars)\n   - Use that many spaces before `.onAs`\n   - Examples:\n     - `A.exact.` → 7 spaces before `.onAs`\n     - `A.sub.` → 5 spaces before `.onAs`\n     - `A.equiv.` → 7 spaces before `.onAs`\n     - `A.awaited.exact.` → 15 spaces before `.onAs`\n","tools/vitest-plugin-examples/README.md":"# Vitest Examples Plugin\n\nA Vite plugin for testing executable documentation examples with type-safe configuration. This plugin automatically discovers example files, generates TypeScript types for type-safe encoder configuration, executes examples, captures their output, and integrates with Vitest's snapshot testing.\n\n## Features\n\n- **Automatic Type Generation**: Generates TypeScript types in `@generated/test-examples` for type-safe encoder configuration\n- **Automatic Discovery**: Finds example files using glob patterns\n- **Output Capture**: Executes examples and captures stdout/stderr using Effect Platform\n- **Dynamic Value Masking**: Type-safe encoder configuration for masking non-deterministic values\n- **Snapshot Testing**: Integrates seamlessly with Vitest inline snapshots\n- **Lifecycle Hooks**: Support for setup/teardown before/after each example\n- **Sequential Execution**: Runs examples sequentially to avoid race conditions\n- **IDE Autocomplete**: Full TypeScript autocomplete for example file paths\n- **Configurable Execution**: Customize executor command, cwd, and environment\n\n## Installation\n\n```bash\npnpm add -D @jasonkuhrt/vitest-plugin-examples\n```\n\nOr use it locally within the Graffle monorepo.\n\n## Usage\n\n### 1. Configure Vitest to Use the Plugin\n\nIn your `vitest.config.ts`:\n\n```typescript\nimport { examplesPlugin } from '@jasonkuhrt/vitest-plugin-examples'\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  plugins: [\n    examplesPlugin({\n      pattern: './*/*.ts',\n      outputDir: './__outputs__',\n    }),\n  ],\n  // ... rest of your config\n})\n```\n\nThe plugin runs during Vite's `buildStart` lifecycle, generating types before TypeScript compilation.\n\n### 2. Use the Convenience Test Function\n\nIn your test file:\n\n```typescript\nimport type { ExamplePath } from '@generated/test-examples'\nimport { createExamplesTest } from '@jasonkuhrt/vitest-plugin-examples'\nimport { test } from 'vitest'\n\n// Type-safe encoder configuration with autocomplete\nconst encoders = {\n  './examples/dynamic-timestamp.ts': (value: string) => {\n    return value.replace(/timestamp: \\d+/g, 'timestamp: MASKED')\n  },\n} satisfies Partial<Record<ExamplePath, EncoderFunction>>\n\ncreateExamplesTest(test, {\n  timeout: 300000,\n  config: {\n    pattern: './*/*.ts',\n    outputDir: './__outputs__',\n    ignore: ['./$', './__outputs__', './__tests__'],\n    encoders,\n    beforeEach: async () => {\n      // Reset database before each example\n      await db.reset()\n    },\n  },\n})\n```\n\nThat's it! The `createExamplesTest()` function:\n\n- Automatically runs all discovered examples\n- Creates a single Vitest test case\n- Generates individual snapshots for each example\n- Handles all assertions internally\n\n### Type-Safe Encoders\n\nThe plugin generates TypeScript types for all discovered example files in `node_modules/@generated/test-examples/`:\n\n```typescript\n// Auto-generated - provides autocomplete for example paths\nexport interface ExampleFiles {\n  './examples/example1.ts': true\n  './examples/example2.ts': true\n  // ... all discovered examples\n}\n\nexport type ExamplePath = keyof ExampleFiles\n```\n\nUse these types for type-safe encoder configuration:\n\n```typescript\nimport type { EncoderFunction, ExamplePath } from '@generated/test-examples'\n\nconst encoders = {\n  './examples/dynamic-values.ts': (output: string) => {\n    return output.replace(/'x-timestamp', '\\d+'/gi, `'x-timestamp', 'MASKED'`)\n  },\n  // ✅ TypeScript autocomplete works here!\n  // ✅ Typos are caught at compile time!\n} satisfies Partial<Record<ExamplePath, EncoderFunction>>\n```\n\n### Advanced: Manual Test Setup\n\nIf you need more control, you can use the lower-level APIs:\n\n```typescript\nimport { runExamples } from '@jasonkuhrt/vitest-plugin-examples'\nimport { expect, test } from 'vitest'\n\ntest('examples', async () => {\n  const results = await runExamples({\n    pattern: './*/*.ts',\n    outputDir: './__outputs__',\n  })\n\n  for (const result of results) {\n    expect(result.encoded).toMatchSnapshot(\n      `${result.file.group}/${result.file.name}`,\n    )\n  }\n}, { timeout: 300000 })\n```\n\n## Configuration\n\n### `ExamplesPluginConfig`\n\n```typescript\ninterface ExamplesPluginConfig {\n  /**\n   * Glob pattern(s) to discover example files.\n   * @default './examples/*\\/*.ts'\n   */\n  pattern?: string | string[]\n\n  /**\n   * Directory where output files will be written.\n   * @default './examples/__outputs__'\n   */\n  outputDir?: string\n\n  /**\n   * Patterns to ignore when discovering examples.\n   * @default ['./examples/$', './examples/__outputs__', './examples/__tests__']\n   */\n  ignore?: string[]\n\n  /**\n   * Custom encoder functions for masking dynamic values in outputs.\n   * Keys are example file paths (relative to project root).\n   */\n  encoders?: Record<string, EncoderFunction>\n\n  /**\n   * Hook called before each example is executed.\n   */\n  beforeEach?: () => Promise<void> | void\n\n  /**\n   * Hook called after each example is executed.\n   */\n  afterEach?: () => Promise<void> | void\n\n  /**\n   * Whether to apply dynamic value masking for test determinism.\n   * @default true\n   */\n  maskDynamicValues?: boolean\n\n  /**\n   * Execution configuration for running examples.\n   */\n  executor?: {\n    /**\n     * Command to execute examples.\n     * @default ['tsx']\n     */\n    command?: string[]\n    /**\n     * Working directory for command execution.\n     * @default process.cwd()\n     */\n    cwd?: string\n    /**\n     * Environment variables to pass to the command.\n     * @default process.env\n     */\n    env?: Record<string, string | undefined>\n  }\n\n  /**\n   * Type generation configuration.\n   */\n  typeGeneration?: {\n    /**\n     * Whether to enable type generation.\n     * @default true\n     */\n    enabled?: boolean\n    /**\n     * Output directory for generated types.\n     * @default 'node_modules/@generated/test-examples'\n     */\n    outputDir?: string\n    /**\n     * Package name for generated types.\n     * @default '@generated/test-examples'\n     */\n    packageName?: string\n  }\n}\n```\n\n### `ExampleResult`\n\n```typescript\ninterface ExampleResult {\n  /** The example file that was executed */\n  file: ExampleFile\n  /** Captured stdout output */\n  stdout: string\n  /** Captured stderr output */\n  stderr: string\n  /** Whether the example failed */\n  failed: boolean\n  /** Exit code from the process */\n  exitCode: number | null\n  /** Encoded output (after applying encoders and masking) */\n  encoded: string\n}\n```\n\n## How It Works\n\n1. **Type Generation** (Vite plugin, `buildStart` hook):\n   - Discovers example files using Kit's `Fs.glob()`\n   - Generates TypeScript types to `node_modules/@generated/test-examples/`\n   - Creates proper npm package with `package.json` for TypeScript module resolution\n   - Runs before TypeScript compilation, ensuring types are available during type checking\n\n2. **Test Execution** (Vitest runtime):\n   - Discovers example files matching the pattern\n   - Runs each example using Effect Platform's `Command` API (configurable executor)\n   - Captures stdout/stderr using Effect Streams\n   - Applies custom encoders + default masking for determinism\n   - Creates individual inline snapshots for each example\n\n### Default Encoding\n\nThe plugin applies default encoding to mask common dynamic values:\n\n- File paths → `/some/path/to/file.ts:XX:XX`\n- Node.js version → `Node.js vXX.XX.XX`\n- Node internal module line numbers\n- Dynamic error formatting differences\n\n## API\n\n### Plugin API\n\n#### `examplesPlugin(config?)`\n\nVite plugin that generates TypeScript types for example files during build.\n\n**Usage**: Add to `vitest.config.ts` plugins array\n\n**Configuration**: Same as `ExamplesPluginConfig`\n\n### Test Helper API\n\n#### `createExamplesTest(test, options?)`\n\nConvenience function that creates a complete test case for all examples.\n\n**Parameters**:\n\n- `test` - Vitest's `test` function\n- `options` - Configuration object:\n  - `config?: ExamplesPluginConfig` - Plugin configuration\n  - `timeout?: number` - Test timeout in milliseconds (default: 300000)\n  - `testName?: string` - Name of the test case (default: 'examples')\n\n**Returns**: void (creates test internally)\n\n#### `testExamples(config?)`\n\nCreates a function that runs all examples with the given configuration.\n\n**Returns**: `() => Promise<ExampleResult[]>`\n\n#### `runExamples(config)`\n\nRuns all examples and returns their results.\n\n**Returns**: `Promise<ExampleResult[]>`\n\n#### `runExample(relativePath, config)`\n\nRuns a single example by its relative path.\n\n**Returns**: `Promise<ExampleResult>`\n\n#### `discoverExamples(config)`\n\nDiscovers example files without executing them.\n\n**Returns**: `Promise<ExampleFile[]>`\n\n#### `captureExample(file, config)`\n\nExecutes a single example file and captures its output.\n\n**Returns**: `Promise<ExampleResult>`\n\n## Migration from Old System\n\nThe old system used:\n\n- `scripts/generate-examples-derivatives/generate-outputs.ts` - Manual output generation\n- Custom `runExample()` and `runExampleForTest()` functions\n- Separate snapshot path construction\n- Manual encoder loading\n\nThe new plugin simplifies this to:\n\n- Single `testExamples()` call\n- Automatic snapshot integration\n- Inline encoder configuration\n- No manual output file generation needed\n\n## Performance\n\n- Examples run **sequentially** (not in parallel) to prevent race conditions\n- Typical run time: ~2-5 minutes for ~30 examples\n- Set test timeout to at least 300000ms (5 minutes)\n\n## Dependencies\n\nThis plugin requires:\n\n- **Effect Platform** (`@effect/platform`, `@effect/platform-node`, `effect`) - For command execution and stream handling\n- **@wollybeard/kit** - For file system operations and FsLoc types\n- **Vite & Vitest** (peer dependencies)\n\n## Limitations\n\n- Executes examples via configurable executor (default: `tsx`)\n- Sequential execution means slower than parallel (by design, for safety)\n- Snapshot comparison happens in-memory (inline snapshots)\n- Generated types live in `node_modules/@generated/` - not committed to git\n- Requires Effect Platform and Kit dependencies\n\n## Future Improvements\n\n- Support for parallel execution with opt-in\n- Option to commit generated types to source control\n- Comparison utilities for validating against old system\n- Support for custom snapshot serializers\n- Lighter-weight alternative without Effect/Kit dependencies\n"},"items":[{"name":"CLAUDE.md","path":"CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/graffle-js/graffle/HEAD/CLAUDE.md","title":"Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"# Local Claude Rules for Graffle Project\n\n## CRITICAL: Generated Files\n\n**NEVER EDIT GENERATED FILES**\n\n- Any file in `__tests__/fixtures/*/modules/` directories is GENERATED\n- These files are created by generator scripts and should NEVER be manually edited\n- If there are issues with generated files, fix the generator code, not the generated output\n- Always regenerate fixtures using the appropriate pnpm scripts after fixing generators\n\nGenerated file patterns to NEVER edit:\n\n- `src/extensions/DocumentBuilder/__tests__/fixtures/*/modules/*.ts`\n- Any file that has been marked as generated or comes from a generator script\n\n## Type Assertion Formatting\n\nWhen using `Ts.Assert` in test files (`.test-d.ts`):\n\n1. **Use alias at module top**: `const A = Ts.Assert`\n2. **Single-line format** for short assertions:\n   ```typescript\n   A.exact.ofAs<string>().onAs<Type>()\n   ```\n3. **Multi-line format** when combined expected + actual types visually exceed ~50 characters:\n   ```typescript\n   A.sub.ofAs<LongExpectedType>()\n     .onAs<LongActualType>()\n   ```\n4. **Indentation rule**: Align the `.onAs` dot with the `.ofAs` dot\n   - Count characters in prefix (e.g., `A.sub.` = 5 chars)\n   - Use that many spaces before `.onAs`\n   - Examples:\n     - `A.exact.` → 7 spaces before `.onAs`\n     - `A.sub.` → 5 spaces before `.onAs`\n     - `A.equiv.` → 7 spaces before `.onAs`\n     - `A.awaited.exact.` → 15 spaces before `.onAs`\n","isInternal":false,"tokens":357,"sizeBytes":1433},{"name":"README.md","path":"tools/vitest-plugin-examples/README.md","rawUrl":"https://raw.githubusercontent.com/graffle-js/graffle/HEAD/tools/vitest-plugin-examples/README.md","title":"vitest-plugin-examples Documentation","category":"plugin-manifest","format":"markdown","content":"# Vitest Examples Plugin\n\nA Vite plugin for testing executable documentation examples with type-safe configuration. This plugin automatically discovers example files, generates TypeScript types for type-safe encoder configuration, executes examples, captures their output, and integrates with Vitest's snapshot testing.\n\n## Features\n\n- **Automatic Type Generation**: Generates TypeScript types in `@generated/test-examples` for type-safe encoder configuration\n- **Automatic Discovery**: Finds example files using glob patterns\n- **Output Capture**: Executes examples and captures stdout/stderr using Effect Platform\n- **Dynamic Value Masking**: Type-safe encoder configuration for masking non-deterministic values\n- **Snapshot Testing**: Integrates seamlessly with Vitest inline snapshots\n- **Lifecycle Hooks**: Support for setup/teardown before/after each example\n- **Sequential Execution**: Runs examples sequentially to avoid race conditions\n- **IDE Autocomplete**: Full TypeScript autocomplete for example file paths\n- **Configurable Execution**: Customize executor command, cwd, and environment\n\n## Installation\n\n```bash\npnpm add -D @jasonkuhrt/vitest-plugin-examples\n```\n\nOr use it locally within the Graffle monorepo.\n\n## Usage\n\n### 1. Configure Vitest to Use the Plugin\n\nIn your `vitest.config.ts`:\n\n```typescript\nimport { examplesPlugin } from '@jasonkuhrt/vitest-plugin-examples'\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  plugins: [\n    examplesPlugin({\n      pattern: './*/*.ts',\n      outputDir: './__outputs__',\n    }),\n  ],\n  // ... rest of your config\n})\n```\n\nThe plugin runs during Vite's `buildStart` lifecycle, generating types before TypeScript compilation.\n\n### 2. Use the Convenience Test Function\n\nIn your test file:\n\n```typescript\nimport type { ExamplePath } from '@generated/test-examples'\nimport { createExamplesTest } from '@jasonkuhrt/vitest-plugin-examples'\nimport { test } from 'vitest'\n\n// Type-safe encoder configuration with autocomplete\nconst encoders = {\n  './examples/dynamic-timestamp.ts': (value: string) => {\n    return value.replace(/timestamp: \\d+/g, 'timestamp: MASKED')\n  },\n} satisfies Partial<Record<ExamplePath, EncoderFunction>>\n\ncreateExamplesTest(test, {\n  timeout: 300000,\n  config: {\n    pattern: './*/*.ts',\n    outputDir: './__outputs__',\n    ignore: ['./$', './__outputs__', './__tests__'],\n    encoders,\n    beforeEach: async () => {\n      // Reset database before each example\n      await db.reset()\n    },\n  },\n})\n```\n\nThat's it! The `createExamplesTest()` function:\n\n- Automatically runs all discovered examples\n- Creates a single Vitest test case\n- Generates individual snapshots for each example\n- Handles all assertions internally\n\n### Type-Safe Encoders\n\nThe plugin generates TypeScript types for all discovered example files in `node_modules/@generated/test-examples/`:\n\n```typescript\n// Auto-generated - provides autocomplete for example paths\nexport interface ExampleFiles {\n  './examples/example1.ts': true\n  './examples/example2.ts': true\n  // ... all discovered examples\n}\n\nexport type ExamplePath = keyof ExampleFiles\n```\n\nUse these types for type-safe encoder configuration:\n\n```typescript\nimport type { EncoderFunction, ExamplePath } from '@generated/test-examples'\n\nconst encoders = {\n  './examples/dynamic-values.ts': (output: string) => {\n    return output.replace(/'x-timestamp', '\\d+'/gi, `'x-timestamp', 'MASKED'`)\n  },\n  // ✅ TypeScript autocomplete works here!\n  // ✅ Typos are caught at compile time!\n} satisfies Partial<Record<ExamplePath, EncoderFunction>>\n```\n\n### Advanced: Manual Test Setup\n\nIf you need more control, you can use the lower-level APIs:\n\n```typescript\nimport { runExamples } from '@jasonkuhrt/vitest-plugin-examples'\nimport { expect, test } from 'vitest'\n\ntest('examples', async () => {\n  const results = await runExamples({\n    pattern: './*/*.ts',\n    outputDir: './__outputs__',\n  })\n\n  for (const result of results) {\n    expect(result.encoded).toMatchSnapshot(\n      `${result.file.group}/${result.file.name}`,\n    )\n  }\n}, { timeout: 300000 })\n```\n\n## Configuration\n\n### `ExamplesPluginConfig`\n\n```typescript\ninterface ExamplesPluginConfig {\n  /**\n   * Glob pattern(s) to discover example files.\n   * @default './examples/*\\/*.ts'\n   */\n  pattern?: string | string[]\n\n  /**\n   * Directory where output files will be written.\n   * @default './examples/__outputs__'\n   */\n  outputDir?: string\n\n  /**\n   * Patterns to ignore when discovering examples.\n   * @default ['./examples/$', './examples/__outputs__', './examples/__tests__']\n   */\n  ignore?: string[]\n\n  /**\n   * Custom encoder functions for masking dynamic values in outputs.\n   * Keys are example file paths (relative to project root).\n   */\n  encoders?: Record<string, EncoderFunction>\n\n  /**\n   * Hook called before each example is executed.\n   */\n  beforeEach?: () => Promise<void> | void\n\n  /**\n   * Hook called after each example is executed.\n   */\n  afterEach?: () => Promise<void> | void\n\n  /**\n   * Whether to apply dynamic value masking for test determinism.\n   * @default true\n   */\n  maskDynamicValues?: boolean\n\n  /**\n   * Execution configuration for running examples.\n   */\n  executor?: {\n    /**\n     * Command to execute examples.\n     * @default ['tsx']\n     */\n    command?: string[]\n    /**\n     * Working directory for command execution.\n     * @default process.cwd()\n     */\n    cwd?: string\n    /**\n     * Environment variables to pass to the command.\n     * @default process.env\n     */\n    env?: Record<string, string | undefined>\n  }\n\n  /**\n   * Type generation configuration.\n   */\n  typeGeneration?: {\n    /**\n     * Whether to enable type generation.\n     * @default true\n     */\n    enabled?: boolean\n    /**\n     * Output directory for generated types.\n     * @default 'node_modules/@generated/test-examples'\n     */\n    outputDir?: string\n    /**\n     * Package name for generated types.\n     * @default '@generated/test-examples'\n     */\n    packageName?: string\n  }\n}\n```\n\n### `ExampleResult`\n\n```typescript\ninterface ExampleResult {\n  /** The example file that was executed */\n  file: ExampleFile\n  /** Captured stdout output */\n  stdout: string\n  /** Captured stderr output */\n  stderr: string\n  /** Whether the example failed */\n  failed: boolean\n  /** Exit code from the process */\n  exitCode: number | null\n  /** Encoded output (after applying encoders and masking) */\n  encoded: string\n}\n```\n\n## How It Works\n\n1. **Type Generation** (Vite plugin, `buildStart` hook):\n   - Discovers example files using Kit's `Fs.glob()`\n   - Generates TypeScript types to `node_modules/@generated/test-examples/`\n   - Creates proper npm package with `package.json` for TypeScript module resolution\n   - Runs before TypeScript compilation, ensuring types are available during type checking\n\n2. **Test Execution** (Vitest runtime):\n   - Discovers example files matching the pattern\n   - Runs each example using Effect Platform's `Command` API (configurable executor)\n   - Captures stdout/stderr using Effect Streams\n   - Applies custom encoders + default masking for determinism\n   - Creates individual inline snapshots for each example\n\n### Default Encoding\n\nThe plugin applies default encoding to mask common dynamic values:\n\n- File paths → `/some/path/to/file.ts:XX:XX`\n- Node.js version → `Node.js vXX.XX.XX`\n- Node internal module line numbers\n- Dynamic error formatting differences\n\n## API\n\n### Plugin API\n\n#### `examplesPlugin(config?)`\n\nVite plugin that generates TypeScript types for example files during build.\n\n**Usage**: Add to `vitest.config.ts` plugins array\n\n**Configuration**: Same as `ExamplesPluginConfig`\n\n### Test Helper API\n\n#### `createExamplesTest(test, options?)`\n\nConvenience function that creates a complete test case for all examples.\n\n**Parameters**:\n\n- `test` - Vitest's `test` function\n- `options` - Configuration object:\n  - `config?: ExamplesPluginConfig` - Plugin configuration\n  - `timeout?: number` - Test timeout in milliseconds (default: 300000)\n  - `testName?: string` - Name of the test case (default: 'examples')\n\n**Returns**: void (creates test internally)\n\n#### `testExamples(config?)`\n\nCreates a function that runs all examples with the given configuration.\n\n**Returns**: `() => Promise<ExampleResult[]>`\n\n#### `runExamples(config)`\n\nRuns all examples and returns their results.\n\n**Returns**: `Promise<ExampleResult[]>`\n\n#### `runExample(relativePath, config)`\n\nRuns a single example by its relative path.\n\n**Returns**: `Promise<ExampleResult>`\n\n#### `discoverExamples(config)`\n\nDiscovers example files without executing them.\n\n**Returns**: `Promise<ExampleFile[]>`\n\n#### `captureExample(file, config)`\n\nExecutes a single example file and captures its output.\n\n**Returns**: `Promise<ExampleResult>`\n\n## Migration from Old System\n\nThe old system used:\n\n- `scripts/generate-examples-derivatives/generate-outputs.ts` - Manual output generation\n- Custom `runExample()` and `runExampleForTest()` functions\n- Separate snapshot path construction\n- Manual encoder loading\n\nThe new plugin simplifies this to:\n\n- Single `testExamples()` call\n- Automatic snapshot integration\n- Inline encoder configuration\n- No manual output file generation needed\n\n## Performance\n\n- Examples run **sequentially** (not in parallel) to prevent race conditions\n- Typical run time: ~2-5 minutes for ~30 examples\n- Set test timeout to at least 300000ms (5 minutes)\n\n## Dependencies\n\nThis plugin requires:\n\n- **Effect Platform** (`@effect/platform`, `@effect/platform-node`, `effect`) - For command execution and stream handling\n- **@wollybeard/kit** - For file system operations and FsLoc types\n- **Vite & Vitest** (peer dependencies)\n\n## Limitations\n\n- Executes examples via configurable executor (default: `tsx`)\n- Sequential execution means slower than parallel (by design, for safety)\n- Snapshot comparison happens in-memory (inline snapshots)\n- Generated types live in `node_modules/@generated/` - not committed to git\n- Requires Effect Platform and Kit dependencies\n\n## Future Improvements\n\n- Support for parallel execution with opt-in\n- Option to commit generated types to source control\n- Comparison utilities for validating against old system\n- Support for custom snapshot serializers\n- Lighter-weight alternative without Effect/Kit dependencies\n","isInternal":false,"tokens":2299,"sizeBytes":10292}],"systemPromptSnippet":"<yakaai_skills repo=\"graffle-js/graffle\">\n<!-- File: CLAUDE.md (Tokens: ~357 | Category: claude-rule) -->\n# Local Claude Rules for Graffle Project\n\n## CRITICAL: Generated Files\n\n**NEVER EDIT GENERATED FILES**\n\n- Any file in `__tests__/fixtures/*/modules/` directories is GENERATED\n- These files are created by generator scripts and should NEVER be manually edited\n- If there are issues with generated files, fix the generator code, not the generated output\n- Always regenerate fixtures using the appropriate pnpm scripts after fixing generators\n\nGenerated file patterns to NEVER edit:\n\n- `src/extensions/DocumentBuilder/__tests__/fixtures/*/modules/*.ts`\n- Any file that has been marked as generated or comes from a generator script\n\n## Type Assertion Formatting\n\nWhen using `Ts.Assert` in test files (`.test-d.ts`):\n\n1. **Use alias at module top**: `const A = Ts.Assert`\n2. **Single-line format** for short assertions:\n   ```typescript\n   A.exact.ofAs<string>().onAs<Type>()\n   ```\n3. **Multi-line format** when combined expected + actual types visually exceed ~50 characters:\n   ```typescript\n   A.sub.ofAs<LongExpectedType>()\n     .onAs<LongActualType>()\n   ```\n4. **Indentation rule**: Align the `.onAs` dot with the `.ofAs` dot\n   - Count characters in prefix (e.g., `A.sub.` = 5 chars)\n   - Use that many spaces before `.onAs`\n   - Examples:\n     - `A.exact.` → 7 spaces before `.onAs`\n     - `A.sub.` → 5 spaces before `.onAs`\n     - `A.equiv.` → 7 spaces before `.onAs`\n     - `A.awaited.exact.` → 15 spaces before `.onAs`\n\n<!-- File: tools/vitest-plugin-examples/README.md (Tokens: ~2299 | Category: plugin-manifest) -->\n# Vitest Examples Plugin\n\nA Vite plugin for testing executable documentation examples with type-safe configuration. This plugin automatically discovers example files, generates TypeScript types for type-safe encoder configuration, executes examples, captures their output, and integrates with Vitest's snapshot testing.\n\n## Features\n\n- **Automatic Type Generation**: Generates TypeScript types in `@generated/test-examples` for type-safe encoder configuration\n- **Automatic Discovery**: Finds example files using glob patterns\n- **Output Capture**: Executes examples and captures stdout/stderr using Effect Platform\n- **Dynamic Value Masking**: Type-safe encoder configuration for masking non-deterministic values\n- **Snapshot Testing**: Integrates seamlessly with Vitest inline snapshots\n- **Lifecycle Hooks**: Support for setup/teardown before/after each example\n- **Sequential Execution**: Runs examples sequentially to avoid race conditions\n- **IDE Autocomplete**: Full TypeScript autocomplete for example file paths\n- **Configurable Execution**: Customize executor command, cwd, and environment\n\n## Installation\n\n```bash\npnpm add -D @jasonkuhrt/vitest-plugin-examples\n```\n\nOr use it locally within the Graffle monorepo.\n\n## Usage\n\n### 1. Configure Vitest to Use the Plugin\n\nIn your `vitest.config.ts`:\n\n```typescript\nimport { examplesPlugin } from '@jasonkuhrt/vitest-plugin-examples'\nimport { defineConfig } from 'vitest/config'\n\nexport default defineConfig({\n  plugins: [\n    examplesPlugin({\n      pattern: './*/*.ts',\n      outputDir: './__outputs__',\n    }),\n  ],\n  // ... rest of your config\n})\n```\n\nThe plugin runs during Vite's `buildStart` lifecycle, generating types before TypeScript compilation.\n\n### 2. Use the Convenience Test Function\n\nIn your test file:\n\n```typescript\nimport type { ExamplePath } from '@generated/test-examples'\nimport { createExamplesTest } from '@jasonkuhrt/vitest-plugin-examples'\nimport { test } from 'vitest'\n\n// Type-safe encoder configuration with autocomplete\nconst encoders = {\n  './examples/dynamic-timestamp.ts': (value: string) => {\n    return value.replace(/timestamp: \\d+/g, 'timestamp: MASKED')\n  },\n} satisfies Partial<Record<ExamplePath, EncoderFunction>>\n\ncreateExamplesTest(test, {\n  timeout: 300000,\n  config: {\n    pattern: './*/*.ts',\n    outputDir: './__outputs__',\n    ignore: ['./$', './__outputs__', './__tests__'],\n    encoders,\n    beforeEach: async () => {\n      // Reset database before each example\n      await db.reset()\n    },\n  },\n})\n```\n\nThat's it! The `createExamplesTest()` function:\n\n- Automatically runs all discovered examples\n- Creates a single Vitest test case\n- Generates individual snapshots for each example\n- Handles all assertions internally\n\n### Type-Safe Encoders\n\nThe plugin generates TypeScript types for all discovered example files in `node_modules/@generated/test-examples/`:\n\n```typescript\n// Auto-generated - provides autocomplete for example paths\nexport interface ExampleFiles {\n  './examples/example1.ts': true\n  './examples/example2.ts': true\n  // ... all discovered examples\n}\n\nexport type ExamplePath = keyof ExampleFiles\n```\n\nUse these types for type-safe encoder configuration:\n\n```typescript\nimport type { EncoderFunction, ExamplePath } from '@generated/test-examples'\n\nconst encoders = {\n  './examples/dynamic-values.ts': (output: string) => {\n    return output.replace(/'x-timestamp', '\\d+'/gi, `'x-timestamp', 'MASKED'`)\n  },\n  // ✅ TypeScript autocomplete works here!\n  // ✅ Typos are caught at compile time!\n} satisfies Partial<Record<ExamplePath, EncoderFunction>>\n```\n\n### Advanced: Manual Test Setup\n\nIf you need more control, you can use the lower-level APIs:\n\n```typescript\nimport { runExamples } from '@jasonkuhrt/vitest-plugin-examples'\nimport { expect, test } from 'vitest'\n\ntest('examples', async () => {\n  const results = await runExamples({\n    pattern: './*/*.ts',\n    outputDir: './__outputs__',\n  })\n\n  for (const result of results) {\n    expect(result.encoded).toMatchSnapshot(\n      `${result.file.group}/${result.file.name}`,\n    )\n  }\n}, { timeout: 300000 })\n```\n\n## Configuration\n\n### `ExamplesPluginConfig`\n\n```typescript\ninterface ExamplesPluginConfig {\n  /**\n   * Glob pattern(s) to discover example files.\n   * @default './examples/*\\/*.ts'\n   */\n  pattern?: string | string[]\n\n  /**\n   * Directory where output files will be written.\n   * @default './examples/__outputs__'\n   */\n  outputDir?: string\n\n  /**\n   * Patterns to ignore when discovering examples.\n   * @default ['./examples/$', './examples/__outputs__', './examples/__tests__']\n   */\n  ignore?: string[]\n\n  /**\n   * Custom encoder functions for masking dynamic values in outputs.\n   * Keys are example file paths (relative to project root).\n   */\n  encoders?: Record<string, EncoderFunction>\n\n  /**\n   * Hook called before each example is executed.\n   */\n  beforeEach?: () => Promise<void> | void\n\n  /**\n   * Hook called after each example is executed.\n   */\n  afterEach?: () => Promise<void> | void\n\n  /**\n   * Whether to apply dynamic value masking for test determinism.\n   * @default true\n   */\n  maskDynamicValues?: boolean\n\n  /**\n   * Execution configuration for running examples.\n   */\n  executor?: {\n    /**\n     * Command to execute examples.\n     * @default ['tsx']\n     */\n    command?: string[]\n    /**\n     * Working directory for command execution.\n     * @default process.cwd()\n     */\n    cwd?: string\n    /**\n     * Environment variables to pass to the command.\n     * @default process.env\n     */\n    env?: Record<string, string | undefined>\n  }\n\n  /**\n   * Type generation configuration.\n   */\n  typeGeneration?: {\n    /**\n     * Whether to enable type generation.\n     * @default true\n     */\n    enabled?: boolean\n    /**\n     * Output directory for generated types.\n     * @default 'node_modules/@generated/test-examples'\n     */\n    outputDir?: string\n    /**\n     * Package name for generated types.\n     * @default '@generated/test-examples'\n     */\n    packageName?: string\n  }\n}\n```\n\n### `ExampleResult`\n\n```typescript\ninterface ExampleResult {\n  /** The example file that was executed */\n  file: ExampleFile\n  /** Captured stdout output */\n  stdout: string\n  /** Captured stderr output */\n  stderr: string\n  /** Whether the example failed */\n  failed: boolean\n  /** Exit code from the process */\n  exitCode: number | null\n  /** Encoded output (after applying encoders and masking) */\n  encoded: string\n}\n```\n\n## How It Works\n\n1. **Type Generation** (Vite plugin, `buildStart` hook):\n   - Discovers example files using Kit's `Fs.glob()`\n   - Generates TypeScript types to `node_modules/@generated/test-examples/`\n   - Creates proper npm package with `package.json` for TypeScript module resolution\n   - Runs before TypeScript compilation, ensuring types are available during type checking\n\n2. **Test Execution** (Vitest runtime):\n   - Discovers example files matching the pattern\n   - Runs each example using Effect Platform's `Command` API (configurable executor)\n   - Captures stdout/stderr using Effect Streams\n   - Applies custom encoders + default masking for determinism\n   - Creates individual inline snapshots for each example\n\n### Default Encoding\n\nThe plugin applies default encoding to mask common dynamic values:\n\n- File paths → `/some/path/to/file.ts:XX:XX`\n- Node.js version → `Node.js vXX.XX.XX`\n- Node internal module line numbers\n- Dynamic error formatting differences\n\n## API\n\n### Plugin API\n\n#### `examplesPlugin(config?)`\n\nVite plugin that generates TypeScript types for example files during build.\n\n**Usage**: Add to `vitest.config.ts` plugins array\n\n**Configuration**: Same as `ExamplesPluginConfig`\n\n### Test Helper API\n\n#### `createExamplesTest(test, options?)`\n\nConvenience function that creates a complete test case for all examples.\n\n**Parameters**:\n\n- `test` - Vitest's `test` function\n- `options` - Configuration object:\n  - `config?: ExamplesPluginConfig` - Plugin configuration\n  - `timeout?: number` - Test timeout in milliseconds (default: 300000)\n  - `testName?: string` - Name of the test case (default: 'examples')\n\n**Returns**: void (creates test internally)\n\n#### `testExamples(config?)`\n\nCreates a function that runs all examples with the given configuration.\n\n**Returns**: `() => Promise<ExampleResult[]>`\n\n#### `runExamples(config)`\n\nRuns all examples and returns their results.\n\n**Returns**: `Promise<ExampleResult[]>`\n\n#### `runExample(relativePath, config)`\n\nRuns a single example by its relative path.\n\n**Returns**: `Promise<ExampleResult>`\n\n#### `discoverExamples(config)`\n\nDiscovers example files without executing them.\n\n**Returns**: `Promise<ExampleFile[]>`\n\n#### `captureExample(file, config)`\n\nExecutes a single example file and captures its output.\n\n**Returns**: `Promise<ExampleResult>`\n\n## Migration from Old System\n\nThe old system used:\n\n- `scripts/generate-examples-derivatives/generate-outputs.ts` - Manual output generation\n- Custom `runExample()` and `runExampleForTest()` functions\n- Separate snapshot path construction\n- Manual encoder loading\n\nThe new plugin simplifies this to:\n\n- Single `testExamples()` call\n- Automatic snapshot integration\n- Inline encoder configuration\n- No manual output file generation needed\n\n## Performance\n\n- Examples run **sequentially** (not in parallel) to prevent race conditions\n- Typical run time: ~2-5 minutes for ~30 examples\n- Set test timeout to at least 300000ms (5 minutes)\n\n## Dependencies\n\nThis plugin requires:\n\n- **Effect Platform** (`@effect/platform`, `@effect/platform-node`, `effect`) - For command execution and stream handling\n- **@wollybeard/kit** - For file system operations and FsLoc types\n- **Vite & Vitest** (peer dependencies)\n\n## Limitations\n\n- Executes examples via configurable executor (default: `tsx`)\n- Sequential execution means slower than parallel (by design, for safety)\n- Snapshot comparison happens in-memory (inline snapshots)\n- Generated types live in `node_modules/@generated/` - not committed to git\n- Requires Effect Platform and Kit dependencies\n\n## Future Improvements\n\n- Support for parallel execution with opt-in\n- Option to commit generated types to source control\n- Comparison utilities for validating against old system\n- Support for custom snapshot serializers\n- Lighter-weight alternative without Effect/Kit dependencies\n</yakaai_skills>"}