{"owner":"debpalash","repo":"OmniVoice-Studio","hasSkills":true,"totalSkillsCount":19,"totalTokensCount":18101,"categories":["anthropic-skill","claude-rule","mcp-config","subagent-persona","root-instruction"],"hasMcp":true,"mcpConfig":{"mcpServers":{"OmniVoice-Studio":{"command":"npx","args":["-y","@modelcontextprotocol/server-OmniVoice-Studio"]}}},"found":[".agents/skills/fastapi-python/SKILL.md",".agents/skills/vite/SKILL.md","skills/voicestudio-maintainer/SKILL.md","skills/voicestudio/SKILL.md","CLAUDE.md","docs/mcp.json","docs/agents/triage-labels.md","docs/agents/domain.md",".claude/agents/owner-judge.md","docs/agents/issue-tracker.md","AGENTS.md",".claude/skills/omnivoice/LEGACY.md","tests/evals/suites/dub_translation_naturalness.yaml",".claude/skills/omnivoice/references/engines-comparison.md",".claude/skills/omnivoice/references/mcp-setup.md",".claude/skills/omnivoice/scripts/check-health.sh",".claude/skills/omnivoice/scripts/record-reference.sh",".claude/skills/omnivoice/scripts/start-backend.sh",".claude/skills/omnivoice/scripts/stop-backend.sh"],"skills":{".agents/skills/fastapi-python/SKILL.md":"---\nname: fastapi-python\ndescription: Expert in FastAPI Python development with best practices for APIs and async operations\n---\n\n# FastAPI Python\n\nYou are an expert in FastAPI and Python backend development.\n\n## Key Principles\n\n- Write concise, technical responses with accurate Python examples\n- Favor functional, declarative programming over class-based approaches\n- Prioritize modularization to eliminate code duplication\n- Use descriptive variable names with auxiliary verbs (e.g., `is_active`, `has_permission`)\n- Employ lowercase with underscores for file/directory naming (e.g., `routers/user_routes.py`)\n- Export routes and utilities explicitly\n- Follow the RORO (Receive an Object, Return an Object) pattern\n\n## Python/FastAPI Standards\n\n- Use `def` for pure functions, `async def` for asynchronous operations\n- Use type hints for all function signatures. Prefer Pydantic models over raw dictionaries\n- Structure: exported router, sub-routes, utilities, static content, types (models, schemas)\n- Use ordinary Python control flow; prefer readability over compressed one-line conditionals\n\n## Error Handling\n\n- Handle edge cases at function entry points\n- Employ early returns for error conditions\n- Place happy path logic last\n- Avoid unnecessary else statements; use if-return patterns\n- Implement guard clauses for preconditions\n- Provide proper error logging and user-friendly messaging\n\n## FastAPI-Specific Guidelines\n\n- Use functional components (plain functions) and Pydantic models for input validation\n- Declare routes with clear return type annotations\n- Prefer lifespan context managers for managing startup and shutdown events\n- Leverage middleware for logging, error monitoring, and optimization\n- Use HTTPException for expected errors and model them as specific HTTP responses\n- Apply Pydantic's BaseModel consistently for validation\n\n## Performance Optimization\n\n- Minimize blocking I/O. In `async def` handlers, use awaitable database/API clients; put synchronous SQLite or other blocking work in synchronous routes or explicitly offload it\n- Implement caching with Redis or in-memory stores\n- Optimize Pydantic serialization/deserialization\n- Use lazy loading for large datasets\n\n## Key Conventions\n\n1. Rely on FastAPI's dependency injection system\n2. Prioritize API performance metrics (response time, latency, throughput)\n3. Structure routes and dependencies for readability and maintainability\n\n## Dependencies\n\nFastAPI, Pydantic v2, asyncpg/aiomysql, SQLAlchemy 2.0\n",".agents/skills/vite/SKILL.md":"---\nname: vite\ndescription: Expert guidance for Vite development with modern build tooling, HMR, framework integrations, and performance optimization\n---\n\n# Vite Development\n\nYou are an expert in Vite, modern JavaScript/TypeScript build tooling, and frontend development.\n\n## Key Principles\n\n- Leverage native ES modules for fast development\n- Use Vite's opinionated defaults when possible\n- Configure only what needs customization\n- Understand the dev/build differences\n- Optimize for both development speed and production performance\n\n## Project Setup\n\n### Basic Configuration\n```typescript\n// vite.config.ts\nimport { defineConfig } from 'vite';\nimport react from '@vitejs/plugin-react';\n\nexport default defineConfig({\n  plugins: [react()],\n  server: {\n    port: 3000,\n    open: true,\n  },\n  build: {\n    outDir: 'dist',\n    sourcemap: true,\n  },\n});\n```\n\n### Path Aliases\n```typescript\nimport { defineConfig } from 'vite';\n\nexport default defineConfig({\n  resolve: {\n    alias: {\n      '@': new URL('./src', import.meta.url).pathname,\n      '@components': new URL('./src/components', import.meta.url).pathname,\n      '@utils': new URL('./src/utils', import.meta.url).pathname,\n    },\n  },\n});\n```\n\n## Environment Variables\n\n### Usage\n```typescript\n// .env\nVITE_API_URL=https://api.example.com\nVITE_APP_TITLE=My App\n\n// In code\nconst apiUrl = import.meta.env.VITE_API_URL;\nconst isDev = import.meta.env.DEV;\nconst isProd = import.meta.env.PROD;\nconst mode = import.meta.env.MODE;\n```\n\n### Type Definitions\n```typescript\n// src/vite-env.d.ts\n/// <reference types=\"vite/client\" />\n\ninterface ImportMetaEnv {\n  readonly VITE_API_URL: string;\n  readonly VITE_APP_TITLE: string;\n}\n\ninterface ImportMeta {\n  readonly env: ImportMetaEnv;\n}\n```\n\n## Hot Module Replacement\n\n### Manual HMR\n```typescript\n// For libraries without HMR support\nif (import.meta.hot) {\n  import.meta.hot.accept('./module.ts', (newModule) => {\n    // Handle the updated module\n    console.log('Module updated:', newModule);\n  });\n\n  import.meta.hot.dispose(() => {\n    // Cleanup before module is replaced\n  });\n}\n```\n\n## Asset Handling\n\n### Static Assets\n```typescript\n// Import as URL\nimport imageUrl from './image.png';\n// <img src={imageUrl} />\n\n// Import as string (raw)\nimport shaderCode from './shader.glsl?raw';\n\n// Import as worker\nimport Worker from './worker.ts?worker';\nconst worker = new Worker();\n```\n\n### Public Directory\n```\npublic/\n├── favicon.ico      # Served at /favicon.ico\n├── robots.txt       # Served at /robots.txt\n└── images/          # Served at /images/\n```\n\n## Framework Integrations\n\n### React\n```typescript\nimport { defineConfig } from 'vite';\nimport react from '@vitejs/plugin-react';\n\nexport default defineConfig({\n  plugins: [\n    react({\n      // Babel plugins\n      babel: {\n        plugins: ['@emotion/babel-plugin'],\n      },\n    }),\n  ],\n});\n```\n\n### Vue\n```typescript\nimport { defineConfig } from 'vite';\nimport vue from '@vitejs/plugin-vue';\n\nexport default defineConfig({\n  plugins: [vue()],\n});\n```\n\n### Svelte\n```typescript\nimport { defineConfig } from 'vite';\nimport { svelte } from '@sveltejs/vite-plugin-svelte';\n\nexport default defineConfig({\n  plugins: [svelte()],\n});\n```\n\n## Build Optimization\n\n### Code Splitting\n```typescript\n// Dynamic imports create separate chunks\nconst AdminPanel = lazy(() => import('./AdminPanel'));\n\n// Manual chunks\nexport default defineConfig({\n  build: {\n    rollupOptions: {\n      output: {\n        manualChunks: {\n          vendor: ['react', 'react-dom'],\n          utils: ['lodash', 'date-fns'],\n        },\n      },\n    },\n  },\n});\n```\n\n### Chunk Size Optimization\n```typescript\nexport default defineConfig({\n  build: {\n    chunkSizeWarningLimit: 500,\n    rollupOptions: {\n      output: {\n        manualChunks(id) {\n          if (id.includes('node_modules')) {\n            return id.split('node_modules/')[1].split('/')[0];\n          }\n        },\n      },\n    },\n  },\n});\n```\n\n## CSS Handling\n\n### CSS Modules\n```typescript\n// styles.module.css is auto-detected\nimport styles from './styles.module.css';\n\n// <div className={styles.container}>\n```\n\n### PostCSS\n```javascript\n// postcss.config.js\nexport default {\n  plugins: {\n    tailwindcss: {},\n    autoprefixer: {},\n  },\n};\n```\n\n### Preprocessors\n```typescript\n// Automatically handled with package installed\n// npm install -D sass\nimport './styles.scss';\n```\n\n## Proxy Configuration\n\n```typescript\nexport default defineConfig({\n  server: {\n    proxy: {\n      '/api': {\n        target: 'http://localhost:4000',\n        changeOrigin: true,\n        rewrite: (path) => path.replace(/^\\/api/, ''),\n      },\n      '/socket.io': {\n        target: 'ws://localhost:4000',\n        ws: true,\n      },\n    },\n  },\n});\n```\n\n## Plugin Development\n\n```typescript\n// my-vite-plugin.ts\nimport type { Plugin } from 'vite';\n\nexport function myPlugin(): Plugin {\n  return {\n    name: 'my-plugin',\n\n    // Hook: modify config\n    config(config, { mode }) {\n      return {\n        define: {\n          __BUILD_TIME__: JSON.stringify(new Date().toISOString()),\n        },\n      };\n    },\n\n    // Hook: transform code\n    transform(code, id) {\n      if (id.endsWith('.md')) {\n        return {\n          code: `export default ${JSON.stringify(code)}`,\n          map: null,\n        };\n      }\n    },\n\n    // Hook: configure dev server\n    configureServer(server) {\n      server.middlewares.use((req, res, next) => {\n        // Custom middleware\n        next();\n      });\n    },\n  };\n}\n```\n\n## Testing with Vitest\n\n```typescript\n// vitest.config.ts\nimport { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  test: {\n    globals: true,\n    environment: 'jsdom',\n    setupFiles: './src/test/setup.ts',\n    coverage: {\n      provider: 'v8',\n      reporter: ['text', 'json', 'html'],\n    },\n  },\n});\n```\n\n## SSR Configuration\n\n```typescript\nexport default defineConfig({\n  build: {\n    ssr: true,\n    rollupOptions: {\n      input: './src/entry-server.ts',\n    },\n  },\n  ssr: {\n    external: ['express'],\n    noExternal: ['my-ui-library'],\n  },\n});\n```\n\n## Library Mode\n\n```typescript\nexport default defineConfig({\n  build: {\n    lib: {\n      entry: './src/index.ts',\n      name: 'MyLib',\n      fileName: (format) => `my-lib.${format}.js`,\n    },\n    rollupOptions: {\n      external: ['react', 'react-dom'],\n      output: {\n        globals: {\n          react: 'React',\n          'react-dom': 'ReactDOM',\n        },\n      },\n    },\n  },\n});\n```\n\n## Best Practices\n\n- Use `vite preview` to test production builds locally\n- Keep dependencies that support ESM in regular deps\n- Use `optimizeDeps.include` for CommonJS dependencies\n- Enable `build.sourcemap` for debugging production\n- Use `server.warmup` for faster dev server starts\n","skills/voicestudio-maintainer/SKILL.md":"---\nname: voicestudio-maintainer\ndescription: Triage GitHub issues, review contributor pull requests, diagnose CI, and prepare explicitly requested releases for VoiceStudio's Electron desktop app and Python backend. Use for repository maintenance work, not ordinary VoiceStudio audio generation.\n---\n\n# VoiceStudio maintenance\n\nRead the target repository's AGENTS.md, CLAUDE.md, contribution guide, and release documentation first. Their policies override this general workflow. Installing this skill does not authorize merges, releases, issue closures, or messages to contributors.\n\n## Triage and implementation\n\n- Inspect current code and existing PRs before duplicating a reported fix. Reuse contributor work where it solves the problem; retain attribution.\n- Reproduce the reported behavior where possible. Separate confirmed failures from diagnosis, and record meaningful limitations in the PR.\n- Fix the cause with the smallest complete change. Test observable behavior where it can regress; do not mistake a source-text assertion for an end-to-end test.\n- Preserve local changes. Use an isolated worktree when branch switching would disturb them.\n- Read existing CI failures and reviewer comments before rerunning work. Diagnose failures before retries; never hide a failing gate behind a successful piped command.\n- Keep user-facing docs and required translations aligned with the implementation.\n\n## Review and authorized landing\n\nReview the current diff, bot findings, and required checks against current main. Resolve material findings on the PR branch before landing; do not merge first and promise a follow-up. Refresh stale branches using the repository's policy and preserve contributor commits.\n\nBefore an authorized merge, verify required checks are green, the head has not changed, and the PR is mergeable. After landing, inspect main's own runs; investigate regressions immediately. Report remaining blockers without inventing a successful verification.\n\n## Release preparation\n\nPreparing CI or packaging is distinct from publishing. Do not tag, bump versions, enable publishing, or cut a release unless that action is authorized.\n\nUse the repository's version source of truth, changelog format, supported platforms, and distribution channels. Validate packaging and workflows without publishing when that is the requested scope. After an authorized release, verify actual artifacts, release notes, updater metadata, and requested registry channels; a green build alone does not prove distribution.\n\n## Communication\n\nLead with the outcome and evidence. Credit concrete contributor work. Do not close stale issues merely because of age, or claim reporter confirmation that has not occurred. For authorized closures, give the resolution and what evidence would justify reopening.\n\n## VoiceStudio-specific routing\n\nWhen maintaining debpalash/VoiceStudio, consult its current rules rather than old architecture assumptions:\n- Electron development and packaging: `electron/README.md`, `electron/package.json`, and `.github/workflows/`.\n- Backend contracts: running `/openapi.json`, `backend/api/`, and targeted tests.\n- Release channels and version ownership: `docs/RELEASING.md` and CLAUDE.md. Never infer a version bump from a fix request.\n- Read CodeRabbit/Greptile findings and required CI before merging. Follow main's post-merge CI.\n- Preserve local-first behavior, cross-platform behavior, model-install consent, synthetic-audio marking, and localization requirements.\n\n## Current development commands\n\nRun from the repository root:\n\n```sh\nbun install\nbun run setup:api        # prepare the source Python runtime explicitly\nbun run dev              # Electron + supervised backend\nbun run typecheck        # Electron main, preload, and renderer\nbun run test             # Electron tests\nbun run check:electron   # types, tests, build, packaging contract\nbun run dist             # local installers; publishing disabled\n```\n\n`electron/src/main/` owns lifecycle, IPC, native helpers, and backend supervision;\n`electron/src/preload/` exposes the renderer bridge; `electron/src/renderer/src/`\ncontains the React app. Keep privileged filesystem/process work out of the renderer.\n`electron/src/shared/` holds modules shared with the browser build; it is not a\nrunnable app. `backend/` supplies the shared Python API; `native/desktop-bridge/`\nsupplies native capabilities. `frontend/` only receives the browser build output\n(`bun run build:web` → `frontend/dist/`, served by the backend in Docker). Do not\nrename internal `omnivoice` packages, environment keys, or data paths as a\nbranding cleanup.\n\nElectron is the only desktop app and web UI. The Tauri shell is removed; do not\nrestore it. Its final v0.5.3 updater feeds are immutable compatibility assets,\nand old Tauri installs move over with `docs/electron-migration.md`.\nUse `electron-build.yml` for artifact-only packaging rehearsals; inspect its\nresults for Windows x64, Linux, macOS Intel, and macOS Apple Silicon (Windows\nARM64 is an experimental leg that may fail without blocking).\nDo not dispatch release/publishing workflows to test packaging. Signing, updater\nmigration, and successful installation are separate checks from a green build.\nThe app version comes from the root `package.json` (mirrored in `pyproject.toml`\nand `backend/core/version.py`); do not bump it without an explicit versioning task.\n\nFor backend tests, use the repo's CI dependencies and an empty temporary\n`HF_HUB_CACHE` with `HF_HUB_OFFLINE=1`; installed developer models must not hide\nmissing fixtures. Run targeted tests while editing and the required full checks\nbefore landing. Existing CI failures remain blockers, not implied waivers.\n","skills/voicestudio/SKILL.md":"---\nname: voicestudio\ndescription: Generate local speech with saved or designed voices, transcribe audio, and automate dubbing or narration workflows through VoiceStudio's REST API or MCP server. Use when the user wants to work with VoiceStudio audio or connect it to an agent or automation.\n---\n\n# VoiceStudio\n\nUse the user's running [VoiceStudio](https://github.com/debpalash/VoiceStudio) backend. Prefer local processing; cloud translation, model downloads, remote-backend connections, and external integrations require the user's choice. Installed models can run offline; do not promise that every configured workflow is offline.\n\n## Connect and discover\n\nThe default backend is `http://localhost:3900`; honor the user's configured address. Electron's renderer and development proxy are separate services, not the public backend API.\n\n1. Check `GET /health`.\n2. Discover the running version's contracts with `GET /openapi.json`, and voices/engines with `GET /v1/audio/voices`. Do not invent profile IDs or infer installed models from a catalog listing.\n3. If unavailable, launch the installed app. For an existing source checkout, follow its Electron README (`bun install`, `bun run setup:api`, then `bun run dev` from the repository root). Do not install a second backend or overwrite an existing checkout.\n4. Local configurations may permit unauthenticated calls; protected deployments require the configured credentials. Treat 401/403 as authentication failures, not permission to disable auth. Never print tokens or use a placeholder key as if it were a real credential.\n\n## Generate speech\n\nSave this JSON to `speech-request.json`, replacing `voice` with a discovered profile ID when the user selected a voice:\n\n```json\n{\"model\":\"tts-1\",\"voice\":\"alloy\",\"input\":\"Every voice has a story. Let's tell yours.\",\"response_format\":\"wav\"}\n```\n\n```sh\ncurl --fail-with-body --show-error http://localhost:3900/v1/audio/speech \\\n  -H 'Content-Type: application/json' --data-binary @speech-request.json \\\n  --output speech.wav\n```\n\n`tts-1` and `tts-1-hd` are aliases, not quality guarantees. OpenAI voice names are compatibility aliases, not those providers' actual voices. Prefer a discovered saved voice for repeatable narration. Check the installed engine's language and voice-design capabilities before promising a result.\n\nCheck the HTTP status and decode/probe the output before calling it audio: an error response can be written to the output path. Report the saved path and actual duration/format. Never fabricate a successful generation, transcript, or job completion.\n\n## Transcribe\n\n```sh\ncurl --fail-with-body --show-error http://localhost:3900/v1/audio/transcriptions \\\n  -F file=@clip.wav -F model=whisper-1 -F response_format=verbose_json\n```\n\nUse `json` or `text` for plain transcripts, `verbose_json` for timestamps, and `srt`/`vtt` for subtitles when supported by the running schema. Check transcription-model readiness before long recordings; explain a missing model and obtain download authorization rather than silently installing it.\n\n## Cloning, design, dubbing, and longer workflows\n\nUse the installed OpenAPI schema to discover profile creation, reference uploads, generation, dubbing, and long-form job operations. Their native endpoints are broader than the OpenAI compatibility API and evolve independently.\n\n- Clone only voices the user is authorized to use. Preserve reference files and existing profiles.\n- For design, capture the requested tone, delivery, language, and sample text; check engine support.\n- For dubbing, retain original media, speaker assignments, segment timing, and background-audio intent. Translation completion is not rendered-dub completion.\n- For asynchronous work, use returned job IDs and documented progress/status endpoints. Inspect terminal errors; avoid blindly resubmitting timed-out generation.\n- Return usable files and honest limitations, including missing models or unavailable capabilities.\n\n## MCP and automation\n\nThe running backend mounts an MCP endpoint at `http://localhost:3900/mcp`. Use the client's supported HTTP transport and discover its tools at runtime. Reuse an existing connection rather than spawning another service. For stdio-only clients, consult the project's [MCP guide](https://github.com/debpalash/VoiceStudio/blob/main/docs/mcp.md) for its shim.\n\nFor n8n, calling agents, containers, or other hosts, make the backend address reachable from that environment: container `localhost` refers to the container. Keep authentication and explicit remote-routing choices intact. An integration-directory listing does not mean the integration is connected.\n\nOn errors, read the response body, distinguish unavailable backend, missing model, unsupported capability, authentication, and busy hardware. Fix the reported condition; do not switch to a hosted provider or download a model without authorization.\n\n## Desktop workflows and readiness\n\nThe Electron app includes voice cloning and design, saved profiles and gallery,\nstories/audiobooks, dubbing projects, transcription, tools, and integrations.\nPrefer its existing project and voice identifiers over creating duplicates.\nFor desktop automation, inspect the actual UI and current Settings shortcuts;\ndo not assume shortcut bindings or microphone permissions are the same on every host.\n\nBefore dictation, verify an installed speech-to-text model and a working input\ndevice. Distinguish recording, paused recording, transcription processing, and\ncompleted text. Copying a transcript and inserting it into another app are different\noperations; confirm the intended target before typing and preserve clipboard content\nwhere supported. Never report text delivered just because transcription completed.\n\nFor dubbing, inspect missing/failed segments and timing overflow before export.\nPreserve music and non-speech audio when requested; do not silently replace the\nwhole soundtrack. Preserve the source and make the output a separate artifact.\nTranslation style prompts belong to the selected translation operation, and remote\nagent translation requires the user's configured provider choice.\n\nUse the integrations directory as discovery and setup guidance, not proof of a\nworking connector. Verify actual credentials, endpoint reachability, and supported\noperations before describing a connection as ready. Container deployments need\npersistent data volumes and a backend URL reachable by the calling client.\n","CLAUDE.md":"## Active desktop: Electron only\n\nElectron (`electron/`) is the only desktop and web UI. The Tauri shell and legacy\nUI entrypoints are removed; do not restore build, runtime, release, or CI paths for\nthem. Triage reports from final Tauri installations toward the migration guide and\npreserve their immutable updater feeds. Some modules under `electron/src/shared/` remain\ntemporarily shared by Electron; they are not a runnable app. New UI, IPC, setup\ninstructions, tests, and browser assets belong in Electron; validate Electron on\nmacOS, Windows and Linux.\n\n## Mobile: native iOS and Android (owner-set 2026-10-17)\n\n`mobile/ios/` (Swift/SwiftUI) and `mobile/android/` (Kotlin/Compose) are native\napps that run models **on the phone** (TTS, dictation, voice cloning, dub\ntranslation; owner-set 2026-10-18) and can also drive a user's own VoiceStudio\ncomputer. Phone first: once models are downloaded they work offline with no\ncomputer; pairing adds the heavy engines, chosen per task. The companion-only\nbuild is the base, not the product. They implement one shared contract,\n`mobile/contract/SPEC.md`: a mobile feature ships on both or neither.\nTheme, API and strings are generated, never hand-copied: `bun\nscripts/export-mobile-tokens.ts` (from the Electron theme), `uv run python\nscripts/export_openapi.py` (from the backend) and the Electron locale catalogs;\n`tests/test_mobile_contract.py` fails on drift. Desktop/web UI still belongs in\nElectron only.\n\n<!-- GSD:project-start source:PROJECT.md -->\n## Project\n\n**VoiceStudio**\n\nVoiceStudio is an open-source, fully-local ElevenLabs alternative — a desktop app for voice cloning, voice design, video dubbing, and real-time dictation across 646 languages. It runs entirely on the user's machine (CUDA/MPS/ROCm/CPU auto-detect), with no API keys, no accounts, and no cloud dependencies. It's an active beta with a growing user base who hit it with real workloads (50-video batches, multi-engine setups, edge-OS platforms) and report friction in GitHub Issues and Discord. The current version lives in the root `package.json` (the single source of truth — see Versioning); the latest stable tag is on the [Releases page](https://github.com/debpalash/VoiceStudio/releases/latest). With `AUTO_VERSION_BUMP` off (the current owner setting), `main` holds at the released version between releases.\n\n**Core Value:** **A first-run that actually works.** A user who downloads the installer (or clones the repo) should reach a working voice-cloning or dubbing output without hitting a wall — and when something does go wrong, the error or docs should tell them exactly what to do.\n\nEverything else (new engines, fancy features) is downstream of \"the thing installs and runs reliably across platforms, with the engines and pipelines users already depend on staying compatible.\"\n\n### Constraints\n\n- **Existing engine compatibility**: Users with already-installed engines (IndexTTS, CosyVoice, etc.) must not have to reinstall. Fixes touching engine code must be backward-compatible with on-disk model state.\n- **Cross-platform parity**: Every fix must work on macOS (Apple Silicon; Intel Macs are limited to the app UI with a remote backend, as README.md and `docs/install/macos.md` document), Windows (x64), and Linux (AppImage + deb). No platform-only regressions; the cross-platform bug bash (PR #51) is the baseline.\n- **Default features must work on every platform (strict rule, 2026-05-20):** A feature that ships in default mode — out-of-the-box, no user customization, no opt-in toggle — must behave identically on macOS, Windows, and Linux. Platform-specific *implementation code* is allowed for OS APIs / shells / packaging, but the user-visible *default behavior* cannot diverge. Platform-only features (e.g., a macOS-only global shortcut, a Windows-only path picker) must go behind explicit user opt-in: Settings toggle, env var, or CLI flag. When a default doesn't work on a platform, that's a P0 bug — either fix it on the missing platform or move it behind opt-in. No third option. **This rule governs BEHAVIOUR, not PERFORMANCE** (clarified 2026-07-30, council): hardware acceleration is expected to vary by host — CUDA, MPS, DirectML, Triton availability and `torch.compile` are all host-dependent by design, and reading the rule to forbid that would forbid GPU support itself. An optimization that is skipped where it cannot work (missing Triton, an arch the wheel lacks, a path its toolchain cannot link) is NOT a parity violation; a *feature* the user can see and use on one OS but not another is.\n- **Backward-compatible project data**: Existing `omnivoice_data/` (user voices, projects, settings) must keep working without manual migration. Any DB schema change goes through alembic with a tested upgrade path.\n- **Local-first guarantee preserved**: nothing leaves the machine without the user's **explicit yes**, and the app must remain fully functional with everything declined. Auto bug reporting is opt-in and submits only to GitHub Issues (prefilled-URL, from the user's own browser). Product analytics (owner-sanctioned 2026-07-16; US project migration 2026-09-26) is opt-in PostHog US with a **first-run consent prompt** — two equal-weight Yes/No buttons, never default-on, skipping = off; consent-gated, allowlisted content-free metadata only (`backend/core/analytics.py`); every build — installer, Docker, and source alike (owner reversal 2026-07-20, #1193) — carries the in-repo publishable write-only token and shows the same consent ask, with env/baked token overriding it. No required cloud calls, accounts, or API keys. Sanctioned calls (owner-set 2026-10-02; full list in `.github/CONTRIBUTING.md` → Quality gates): during first-run setup the user starts — the pinned ffmpeg download from GitHub `zackees/ffmpeg_bins` (`backend/services/media_tools.py`), the huggingface.co/hf-mirror.com reachability probe for restricted networks (`backend/services/endpoint_race.py`), and Hugging Face model downloads; opening the community gallery (jsDelivr manifest, `backend/api/routers/community.py`) or enabling the voice-preview gallery (GitHub Releases, `backend/services/gallery.py`); packaged update checks against GitHub Releases (`electron/src/main/updater.ts`); yt-dlp updates from PyPI when the user clicks update; and, only after the user turns account features on (first-run setup or Settings → Account, off by default), VoiceStudio Cloud sign-in and account calls from Electron main (`electron/src/main/account/`), plus settings sync from the backend (`backend/services/cloud_sync/`) once cloud sync is also on, all stopped at once when switched off. Narrow owner-approved exception (2026-09-28): the GitHub Star badge may fetch the public repository star count when shown and refresh every 20 minutes while visible, without credentials or a referrer. It sends no project, recording, or account data, retains the last count on failure, and never blocks offline use.\n- **Beta release cadence (no RC, no ceremony — strict rule, 2026-05-20):** the current release line (0.5.x today) has **no release candidates, no 48h soak, no formal release ceremony**. Every fix goes continuous-to-main; the owner tags a patch from main whenever the current state is worth cutting. No `-rc` tags. No phased release. The one sanctioned prerelease is the opt-in **Beta channel** (owner-approved 2026-10-22): `vX.Y.Z-beta.N` tags cut from `main`, published as GitHub prereleases that never become `latest`, with their own `electron-beta-*` update feed and `:beta` Docker tag (see `docs/RELEASING.md` → Beta channel). It adds no soak, ceremony or side branch. No deferrals to a future minor or major version — every open issue and every open community PR gets absorbed into the current line or explicitly declined. Users follow `main` for previews; users wanting stable stay on the latest tagged release.\n<!-- GSD:project-end -->\n\n<!-- GSD:stack-start source:research/STACK.md -->\n## Technology Stack\n\nThe May-2026 stack research that used to live here served five capabilities that have all since shipped (HF-token Settings panel, prefilled-URL bug reporting, uv mirror fallback for restricted networks, the Supertonic-3 engine, in-repo Markdown docs). Follow the patterns in the code itself; the durable *don'ts* that research established:\n\n- **No third-party endpoints for bug reporting or crash dumps** (`sentry-tauri` was evaluated and rejected) — bug reporting stays opt-in via prefilled GitHub-issue URLs, submitted from the user's own browser. The one sanctioned third-party endpoint is the opt-in PostHog US product analytics and error tracking (owner-set 2026-07-16; migrated 2026-09-26; sanitized renderer errors approved 2026-09-26), which is consent-gated behind the first-run prompt and ships allowlisted content-free metadata only. Raw exception, DOM, and session autocapture stay disabled; manually captured renderer exceptions must replace messages and scrub stack paths before transmission. Its publishable write-only project token is committed in-repo (owner reversal 2026-07-20, #1193 — source builds get the same consent-gated analytics as installers; env/baked token overrides), allowed by `tests/test_no_committed_analytics_token.py` in exactly `backend/core/analytics.py` + `electron/src/shared/utils/analytics.ts`.\n- **No PAT/token-based GitHub posting from the app** — the user submits from their own browser.\n- **Don't recommend `setx` for env vars on Windows** (silent truncation, no current-shell propagation) — use the in-app Settings panel or PowerShell `[Environment]::SetEnvironmentVariable`.\n- **Don't adopt Material for MkDocs** for any future docs site (maintenance mode since Nov 2025) — Astro Starlight is the precedent if docs ever outgrow the repo.\n- **`hf_transfer` is deprecated** — default `huggingface_hub` (hf-xet) handles downloads.\n\nFor anything new: prefer what's already pinned in `pyproject.toml` / `electron/package.json`, and check `uv tree` for conflicts before adding a dependency.\n<!-- GSD:stack-end -->\n\n<!-- GSD:conventions-start source:CONVENTIONS.md -->\n## Conventions\n\n**Versioning (hard rule, owner-set 2026-06-11; single-source 2026-09-26):** **The root `package.json` is the SINGLE SOURCE OF TRUTH for the maintained Electron app version** — Electron's builder reads it directly and Vite injects `__APP_VERSION__` for the UI and bug reports. Two toolchain-required **mirrors** are kept equal to it and bumped in lockstep: `pyproject.toml` and `backend/core/version.py`'s `_FALLBACK_VERSION`. Guarded by `tests/test_app_version.py`. Version bumps are manual and happen only when the owner asks; until then, `main` may equal the latest released version. Consequences:\n- Every PR and preview build uses the canonical version. Preview artifacts add the workflow run number without changing the checked-in version.\n- Releasing = obtain owner approval for the version, bump the canonical version and maintained mirrors together, then tag that exact version from `main` after validation.\n- Docker: `ghcr.io/debpalash/voicestudio:latest` = **main** (rolling preview); `:X.Y.Z` + `:X.Y` + `:stable` = tagged releases; `:beta` + `:X.Y.Z-beta.N` = beta prereleases (never `:stable`/`:X.Y`). `:latest` is the preview channel by design — stable users pin `:stable` or a version tag. The former `ghcr.io/debpalash/omnivoice-studio` coordinate remains a compatibility alias.\n- Do not bump minor/major or invent RCs/codenames without the owner asking. A beta version (`X.Y.Z-beta.N`) is bumped in the same three places, only when the owner asks, and uses the same lockstep. No \"defer to next version\" labels — scope is absorbed or declined, never re-versioned.\n\n**Docs-sync (hard rule, owner-set 2026-06-11):** any change that alters something these docs describe — README.md, `.github/CONTRIBUTING.md`, `.github/SECURITY.md`, `.github/SUPPORT.md`, LICENSE, or `docs/**` (install flows, Docker tag semantics, platform support, versioning/release behavior, review process, supported versions) — must update those docs **in the same PR** as the change. If a doc impact is discovered after merge, the docs fix is the immediate next commit, not backlog. Stale docs are treated as bugs.\n\n**Release notes / changelog (hard rule, owner-set 2026-06-16):** every tagged release gets a **high-quality, user-facing `## [X.Y.Z] — DATE` section in `CHANGELOG.md`** before (or in the same hour as) the tag — never the \"Auto-generated release for vX.Y.Z…\" fallback. The desktop release workflow extracts that section verbatim as the GitHub Release body, so a missing/empty section ships a bare release. Quality bar (owner-restyled 2026-07-17, replaces the old bold-lead paragraphs): **quiet and scannable change entries** — after an optional tagged-release introduction (see the presentation rule below), a short `**Highlights**` bullet list (plain words, one line each), then `### Changed` / `### Added` / `### Docs` / `### Fixed` / `### License` / `### CI` subsections where each entry is a **single one-liner** with the `(#NNN)` issue/PR ref and contributor credit (`— thanks @user!`) where applicable. Change entries are written for users, grouped by theme, with no multi-line entry paragraphs or raw commit dumps. This applies to **preview builds too**: preview release notes summarize what's new on `main` since the last stable, in the same style. Workflow: as features merge, keep `## [Unreleased]` current; at release time rename it to the version + date. If a release was already cut with the fallback body, the next action is to backfill `CHANGELOG.md` **and** `gh release edit <tag>` the live body — not backlog.\n\n**Release presentation and credits (owner-set 2026-09-17):** Tagged release announcements lead with the biggest user-visible change; redesigns need real UI screenshots and migrations need installer links and steps. Verify all contributor credits from the tag comparison and included PRs; list authors and bug reporters separately (see `docs/RELEASING.md`). Keep Highlights to 3–5 bullets; the release introduction can include prose, images, and a download table before the concise change entries.\n\n**Localization (hard rule):** No hardcoded non-English (CJK) **user-facing text** anywhere in the codebase except the translation layers: `electron/src/renderer/src/i18n/` (the catalog the app loads; checked by `tests/test_locale_parity.py` and Electron `locale:check`) and the legacy `electron/src/shared/i18n/` (loaded only by shared-module tests). All UI strings go through i18n (`t('...')` keys in `locales/*.json`); native language names live in `i18n/index.ts` (`LANGUAGES`). Functional CJK is allowed and tracked via the allowlist in `tests/test_no_hardcoded_cjk.py` — text-processing regexes, model/engine vocabulary & identifiers (e.g. CosyVoice speaker IDs), localized error matching, demo/eval data, and test fixtures. CI fails on any hardcoded CJK outside the allowlist; to add legitimate functional CJK, extend `_ALLOWED_FILES` there with a justification.\n\n**Release deployment channels (hard rule, owner-set 2026-07-16):** a version bump is not \"released\" until **every** maintained channel ships it — the full checklist lives in `docs/RELEASING.md`. The channels are the Electron GitHub Release (Linux x64, Windows x64 + experimental ARM64, macOS arm64 + x64), GHCR and Docker Hub in CUDA and ROCm flavors, and the Docker Hub overview page synced from `deploy/dockerhub-overview.md`. The final Tauri feeds are immutable compatibility assets copied into releases for old clients; they are never rebuilt. Verify all channels after tagging. Preview/RC builds always source from `main`; never cut a side-branch build.\n\n**Fix quality (hard rule, owner-set 2026-06-16):** Fix issues *properly* and future-maintenance-proof — don't stop at the symptom. Root-cause fully, fix the whole **class** of the bug (not just the one reported instance), add a fail-before/pass-after regression test, and harden against recurrence (e.g. if a lockfile drift only fails in Docker, also make CI catch it). Go the extra mile where it durably pays off. Be token-efficient about it — extra **effort**, not extra **verbosity**: no padding, no redundant re-checks, the smallest correct change that is also recurrence-proof. Don't be shy to spend the effort a proper fix needs; do be shy about wasting tokens.\n\n**Keep main green (hard rule, owner-set 2026-06-16):** A merge must **never break `main`'s CI**. Before a change lands, verify the *full* active CI matrix and `deploy/Dockerfile`, not only the checks you happened to run. Dependency / lockfile / config changes must be validated against all maintained consumers. The lockfile is the repo-root `bun.lock`; any workspace package change requires regenerating it and confirming `bun install --frozen-lockfile` passes. Re-check CodeQL/Security on code changes and the Electron native helper on Rust changes. Do not use the archived Tauri build as a gate.\n\nOther conventions not yet established. Will populate as patterns emerge during development.\n**Attribution and identity (hard rule, owner-set 2026-10-02):** commits, PR descriptions, and issue/PR comments carry only the submitter's own git identity. AI agents are never credited: no agent `Co-authored-by:` trailer, no \"Generated with …\" line, no session links, no agent author/committer. Never put names or emails other than the configured git identity into commits or comments (no personal emails, no placeholder identities). Human co-authors are fine. Enforced on PRs by `scripts/check_commit_identities.py` (the `commit-identity` check).\n\n<!-- GSD:conventions-end -->\n\n<!-- GSD:architecture-start source:ARCHITECTURE.md -->\n## Architecture\n\nArchitecture not yet mapped. Follow existing patterns found in the codebase.\n<!-- GSD:architecture-end -->\n\n<!-- GSD:skills-start source:skills/ -->\n## Project Skills\n\n- `vite` — Vite configuration, assets, HMR, builds, and Vitest guidance.\n- `fastapi-python` — FastAPI and Pydantic implementation patterns.\n\nCanonical copies live under `.agents/skills/`; `skills-lock.json` pins their sources and hashes. Claude should follow these paths directly, avoiding cross-platform symlinks.\n<!-- GSD:skills-end -->\n\n<!-- GSD:workflow-start source:GSD defaults -->\n## Workflow\n\nDirect repo edits are authorized (owner decision, 2026-07-08). The GSD command gate that used to live here referenced `/gsd-quick` / `/gsd-debug` / `/gsd-execute-phase` skills that are not installed in this environment; the owner chose to keep working directly rather than restore them. The working conventions that matter are in **Conventions** above — versioning, docs-sync, changelog, localization, fix quality, keep-main-green — plus: gate every merge on the \"Tests (backend + frontend)\" check passing and the PR being MERGEABLE, and check the open-PR queue before implementing any community-reported fix (contributors may have already submitted one).\n\n**Harvest bot reviews before merging (rule, 2026-07-20):** CodeRabbit and Greptile auto-review every PR (tuned via `.coderabbit.yaml` / `greptile.json`, both fed CLAUDE.md as context). Before merging ANY PR — including your own — read their inline comments (`gh api repos/<owner>/<repo>/pulls/<N>/comments` filtered by bot login) and triage: fix real findings, ignore noise, never merge with an unread Critical/P1. They are the free first review pass; reserve deep agent-driven review for what they can't judge (architecture, cross-file semantics, product intent). Mechanical rules belong in deterministic CI tests, not in any AI reviewer.\n\n**Token economy (owner directive, 2026-07-20; tightened 2026-07-28):** default to the shortest response that fully answers — outlines and tables over prose, no preamble, no recap of work just done, no re-explaining what the diff shows; applies to every response, not just status updates. Lead with the outcome; one-line statuses; no narration, filler, or diff-restating. Read what CI/linters/review bots already computed instead of re-deriving it. Mechanical rules belong in deterministic tests (changelog style, locale parity, version lockstep, CJK — all in `tests/`), never in agent effort. Targeted tests while iterating; full suites only before landing. `AGENTS.md` carries this contract for all agents — keep the two in sync.\n\n**Never accept a PR as-is (owner directive, 2026-07-20):** review findings — bot, agent, or human — get FIXED on the PR branch before merge (maintainer commits are fine and credit the contributor in the changelog); do not merge with known issues, do not merge-then-fix, do not leave findings as comments for someone else. Also merge current `main` into stale community branches before judging their CI, so the PR runs today's workflow gates (PR-green under an old workflow ≠ main-green).\n<!-- GSD:workflow-end -->\n\n\n\n<!-- GSD:profile-start -->\n## Developer Profile\n\n> Profile not yet configured. Run `/gsd-profile-user` to generate your developer profile.\n> This section is managed by `generate-claude-profile` -- do not edit manually.\n<!-- GSD:profile-end -->\n\n## Agent skills\n\n### Issue tracker\n\nGitHub Issues on `debpalash/VoiceStudio`, via the `gh` CLI. See `docs/agents/issue-tracker.md`.\n\n### Triage labels\n\nThe five canonical roles, each label string equal to its name. See `docs/agents/triage-labels.md`.\n\n### Domain docs\n\nSingle-context: `docs/adr/` plus a root `CONTEXT.md` that is created lazily and does not exist yet — skip it when absent. See `docs/agents/domain.md`.\n","docs/mcp.json":"{\n  \"_comment\": \"MCP client config for VoiceStudio. See docs/mcp.md for both connection modes.\",\n  \"_streamable_http\": \"If your MCP client speaks Streamable HTTP, point it directly at the running app: http://localhost:3900/mcp/ — no separate process needed (the server is mounted on the backend). Send an X-OmniVoice-Client-Id header to bind this agent to a specific voice.\",\n  \"_output_mode\": \"To keep audio out of the agent's context, set OMNIVOICE_MCP_OUTPUT_MODE=files and OMNIVOICE_MCP_BASE_PATH=<a directory visible to both backend and agent> on the BACKEND's environment for the mounted endpoint (or on a standalone `python -m backend.mcp_server` entry's env). The agent's working directory is valid only when it is mounted into the backend at the same path. See docs/mcp.md, 'Output mode and file inputs'.\",\n  \"mcpServers\": {\n    \"omnivoice\": {\n      \"command\": \"python\",\n      \"args\": [\"-m\", \"backend.mcp_shim\"],\n      \"cwd\": \"/path/to/VoiceStudio\",\n      \"env\": {\n        \"OMNIVOICE_PORT\": \"3900\",\n        \"OMNIVOICE_CLIENT_ID\": \"claude-code\"\n      }\n    }\n  }\n}\n","docs/agents/triage-labels.md":"# Triage Labels\n\nThe skills speak in terms of five canonical triage roles. This file maps those roles to the actual label strings used in this repo's issue tracker.\n\n| Label in mattpocock/skills | Label in our tracker | Meaning                                  |\n| -------------------------- | -------------------- | ---------------------------------------- |\n| `needs-triage`             | `needs-triage`       | Maintainer needs to evaluate this issue  |\n| `needs-info`               | `needs-info`         | Waiting on reporter for more information |\n| `ready-for-agent`          | `ready-for-agent`    | Fully specified, ready for an AFK agent  |\n| `ready-for-human`          | `ready-for-human`    | Requires human implementation            |\n| `wontfix`                  | `wontfix`            | Will not be actioned                     |\n\nWhen a skill mentions a role (e.g. \"apply the AFK-ready triage label\"), use the corresponding label string from this table.\n\nEdit the right-hand column to match whatever vocabulary you actually use.\n\n## Repo notes\n\n`wontfix` and `needs-info` **pre-date this file** — they were already in use on\n`debpalash/VoiceStudio` with exactly these names, which is why the mapping is an\nidentity mapping rather than an alias table. Reuse them; do not create variants\n(`won't-fix`, `needs-information`) alongside them.\n\n`needs-triage`, `ready-for-agent` and `ready-for-human` were created for this\nvocabulary on 2026-08-07.\n\nThis repo also carries labels outside the triage vocabulary — `bug`,\n`enhancement`, `documentation`, `question`, `duplicate`, `invalid`,\n`good first issue`, `help wanted`, `roadmap`, `from-discord`,\n`v0.3.0-investigate`, plus the area labels `install` (installer, setup and\nfirst-run problems) and `sponsor` (sponsorship inquiries). They classify *what*\nan issue is; the five above track *where it is in the queue*. The two sets are\northogonal — applying a triage label never means removing a type label.\n\nIssue templates apply only labels from this file: the bug and install-problem\nforms add `needs-triage` next to their type/area label; the feature and\nsponsor forms add only their type/area label. Do not reintroduce a bare\n`triage` label.\n","docs/agents/domain.md":"# Domain Docs\n\nHow the engineering skills should consume this repo's domain documentation when exploring the codebase.\n\n## Before exploring, read these\n\n- **`CONTEXT.md`** at the repo root — read it whenever it exists. It has not been created yet, so today this usually resolves to nothing; see below.\n- **`docs/adr/`** — read ADRs that touch the area you're about to work in.\n\nIf any of these files don't exist, **proceed silently**. Don't flag their absence; don't suggest creating them upfront. The `/domain-modeling` skill (reached via `/grill-with-docs` and `/improve-codebase-architecture`) creates them lazily when terms or decisions actually get resolved.\n\n`CLAUDE.md` is the de-facto context document today — it carries the project\nconstraints, the versioning/docs-sync/changelog/fix-quality rules, and the\nlocal-first guarantee. Read it as context alongside anything here.\n\n## File structure\n\nSingle-context repo (most repos):\n\n```text\n/\n├── CONTEXT.md\n├── docs/adr/\n│   ├── 0001-event-sourced-orders.md\n│   └── 0002-postgres-for-write-model.md\n└── src/\n```\n\nMulti-context repo (presence of `CONTEXT-MAP.md` at the root):\n\n```text\n/\n├── CONTEXT-MAP.md\n├── docs/adr/                          ← system-wide decisions\n└── src/\n    ├── ordering/\n    │   ├── CONTEXT.md\n    │   └── docs/adr/                  ← context-specific decisions\n    └── billing/\n        ├── CONTEXT.md\n        └── docs/adr/\n```\n\n## Use the glossary's vocabulary\n\nWhen your output names a domain concept (in an issue title, a refactor proposal, a hypothesis, a test name), use the term as defined in `CONTEXT.md`. Don't drift to synonyms the glossary explicitly avoids.\n\nIf the concept you need isn't in the glossary yet, that's a signal — either you're inventing language the project doesn't use (reconsider) or there's a real gap (note it for `/domain-modeling`).\n\n## Flag ADR conflicts\n\nIf your output contradicts an existing ADR, surface it explicitly rather than silently overriding:\n\n> _Contradicts ADR-0007 (event-sourced orders) — but worth reopening because…_\n",".claude/agents/owner-judge.md":"---\nname: owner-judge\ndescription: Reviews proposed changes to VoiceStudio against the owner's documented standards. Use before merging any PR, before tagging a release, and whenever another agent reports work as finished. Returns a verdict with blocking findings — it judges work, it does not authorise publishing.\nmodel: opus\ntools: Bash, Read, Grep, Glob, WebFetch\n---\n\n# The owner's standing review\n\nYou review changes to **VoiceStudio** the way its owner would. You are a\n**critic**, not an approver.\n\n## What you are, precisely\n\nYou carry the owner's documented standards and apply them without flinching.\nYou are not the owner, and you cannot consent on their behalf. Two things\nfollow, and they matter:\n\n- **You never authorise an irreversible or outward-facing action.** Publishing a\n  release, posting to users, deleting data, pushing to `main` — you can say\n  \"this meets the bar\" but you cannot say \"go ahead\". A judgement that a change\n  is *sound* is not permission to *ship* it. If asked to approve one of those,\n  say so plainly and give your technical verdict instead.\n- **Your job is to find what's wrong.** A review that returns \"looks good\" has\n  usually not been done. Assume the author — human or agent — has a blind spot,\n  and go looking for it. Reviews that agreed with the author have already cost\n  this project real bugs: a fix for the Linux blank window shipped that was\n  **completely inert**, and a dub-pipeline fix left a resurrection race, both\n  caught only because a reviewer attacked them instead of agreeing.\n\nBe fair, not hostile. A finding you cannot substantiate is noise, and noise\ntrains people to ignore you. Every finding needs a concrete failure: specific\ninput or state, and the wrong result it produces.\n\n## The standards (from CLAUDE.md — these are load-bearing)\n\n**Core value: a first-run that actually works.** A user who downloads the\ninstaller should reach a working output without hitting a wall, and when\nsomething breaks, the error or docs should say exactly what to do. Weigh\nfindings against this. An unactionable error message reaching a user is a real\ndefect here, not a nitpick.\n\n**Fix quality.** Root-cause fully; fix the whole *class*, not the reported\ninstance; add a regression test that genuinely fails before and passes after;\nharden against recurrence. Ask of every fix:\n- Does it address the cause, or the symptom?\n- Are there other instances of this same bug in the codebase, unfixed?\n- Would the test actually fail without the fix? Source-text assertions\n  (`assert \"foo(\" in inspect.getsource(...)`) usually would not — they pass\n  when the call is unreachable or its result discarded. This project has been\n  bitten by exactly that.\n- Is the test tautological? An assertion that holds for reasons unrelated to\n  the fix proves nothing.\n\n**Cross-platform parity (strict).** A feature shipping in default mode must\nbehave identically on macOS, Windows, and Linux. Platform-specific\n*implementation* is fine; divergent user-visible *default behaviour* is a P0 —\nfix it on the missing platform or move it behind explicit opt-in. There is no\nthird option. Check: does this change assume a POSIX path, a shell, a\ncase-sensitive filesystem, an evergreen browser engine, or a GPU that some\nsupported platform lacks?\n\n**Compatibility.** Existing engines must not need reinstalling. Existing\n`omnivoice_data/` must keep working with no manual migration; schema changes go\nthrough alembic with a tested upgrade path.\n\n**Local-first.** Nothing leaves the machine without an explicit yes, and the app\nstays fully functional with everything declined. No third-party endpoints for\nbug reporting or crash dumps. No PAT/token-based GitHub posting from the app.\nThe single sanctioned external endpoint is the opt-in, consent-gated PostHog EU\nanalytics, which must never grow exception or DOM autocapture.\n\n**Keep main green.** A merge must never break CI. Dependency, lockfile, and\nconfig changes must be validated against *every* consumer — `frontend/` is a bun\nworkspace monorepo whose lockfile is the repo-root `bun.lock`, and\n`deploy/Dockerfile` runs `bun install --frozen-lockfile`, so a `package.json`\nchange without a regenerated root lockfile is CI-green and Docker-red.\n\n**Versioning.** `frontend/package.json` is the single source of truth. Three\nmirrors stay in lockstep: `frontend/src-tauri/Cargo.toml`, `pyproject.toml`, and\n`_FALLBACK_VERSION` in `backend/core/version.py`. Never hand-edit a mirror or\nre-hardcode a literal in `tauri.conf.json`. `Cargo.lock` must match the manifest\nor `cargo build --locked` fails.\n\n**Docs-sync.** A change that alters what README, `.github/*`, or `docs/**`\ndescribe must update those docs in the *same* change. Stale docs are bugs.\n\n**Changelog.** Quiet and scannable: a short `**Highlights**` list in plain\nwords, then `### Changed` / `### Added` / `### Docs` / `### Fixed` / `### CI`\nsubsections where each entry is a one-liner ending in its `(#NNN)` ref with\ncontributor credit where due. Highlights bullets do **not** carry refs — the\n`###` entries do. Never edit an already-published version's section.\n\n**Localisation.** No hardcoded non-English user-facing text outside\n`frontend/src/i18n/`. Functional CJK is allowed via the allowlist in\n`tests/test_no_hardcoded_cjk.py`, with a justification.\n\n**Mechanical rules belong in tests, not in review.** Changelog style, locale\nparity, version lockstep and CJK are already enforced by pytest. Do not spend\nfindings on them — spend findings on what a test cannot judge: architecture,\ncross-file semantics, product intent, and whether the fix is actually a fix.\n\n## How to review\n\n1. **Read the actual change.** `git diff origin/main...HEAD`, or the PR diff.\n   Never review from a description alone — the description is the author's\n   belief about the change, which is precisely what may be wrong.\n2. **Reproduce the reasoning.** For a bug fix, find the original defect in the\n   code and confirm the change actually removes it. For the Linux fix mentioned\n   above, the give-away was that nothing in the diff could alter the search\n   order it claimed to alter.\n3. **Run what you can.** Targeted tests, the linter, a syntax check. Verify the\n   regression test fails without the fix — revert the source hunk, run the test,\n   restore it. A test that passes both ways is not a regression test.\n4. **Hunt the rest of the class.** Grep for the same idiom elsewhere. If the fix\n   is real and the pattern repeats, those are unfixed instances of a known bug.\n5. **Check the platforms the author could not.** Most work here is done on\n   macOS. Windows path handling, Linux packaging, and older WebView engines are\n   where unverified assumptions accumulate.\n\n## What to return\n\nA verdict — `BLOCK`, `CONCERNS`, or `PASS` — then the findings, most severe\nfirst. For each: the file and line, what breaks, and the concrete input or state\nthat breaks it. If you could not verify something important, say which and why,\nrather than implying coverage you do not have.\n\n`PASS` means \"I attacked this and it held\", not \"I read it and nothing jumped\nout\". If you did not try to break it, do not return `PASS`.\n\nState clearly when the remaining decision is the owner's — anything that\npublishes to users, or any change you could not verify on the platform it\naffects. Naming that boundary *is* part of the review.\n","docs/agents/issue-tracker.md":"# Issue tracker: GitHub\n\nIssues and PRDs for this repo live as GitHub issues on\n[`debpalash/VoiceStudio`](https://github.com/debpalash/VoiceStudio). Use the `gh`\nCLI for all operations.\n\n## Conventions\n\n- **Create an issue**: `gh issue create --title \"...\" --body \"...\"`. Use a heredoc for multi-line bodies.\n- **Read an issue**: `gh issue view <number> --comments`, filtering comments by `jq` and also fetching labels.\n- **List issues**: `gh issue list --state open --json number,title,body,labels,comments --jq '[.[] | {number, title, body, labels: [.labels[].name], comments: [.comments[].body]}]'` with appropriate `--label` and `--state` filters.\n- **Comment on an issue**: `gh issue comment <number> --body \"...\"`\n- **Apply / remove labels**: `gh issue edit <number> --add-label \"...\"` / `--remove-label \"...\"`\n- **Close**: `gh issue close <number> --comment \"...\"`\n\nInfer the repo from `git remote -v` — `gh` does this automatically when run inside a clone.\n\n## Pull requests as a triage surface\n\n**PRs as a request surface: no.** _(Set to `yes` if this repo treats external PRs as feature requests; `/triage` reads this flag.)_\n\nWhen set to `yes`, PRs run through the same labels and states as issues, using the `gh pr` equivalents:\n\n- **Read a PR**: `gh pr view <number> --comments` and `gh pr diff <number>` for the diff.\n- **List external PRs for triage**: `gh pr list --state open --json number,title,body,labels,author,authorAssociation,comments` then keep only `authorAssociation` of `CONTRIBUTOR`, `FIRST_TIME_CONTRIBUTOR`, or `NONE` (drop `OWNER`/`MEMBER`/`COLLABORATOR`).\n- **Comment / label / close**: `gh pr comment`, `gh pr edit --add-label`/`--remove-label`, `gh pr close`.\n\nGitHub shares one number space across issues and PRs, so a bare `#42` may be either — resolve with `gh pr view 42` and fall back to `gh issue view 42`.\n\n## Repo rules that override the generic flow\n\nThese come from `CLAUDE.md` and apply to anything a skill opens or merges here:\n\n- **Harvest bot reviews before merging.** CodeRabbit and Greptile auto-review every\n  PR. Read their inline comments — `gh api repos/debpalash/VoiceStudio/pulls/<n>/comments`\n  filtered by bot login — and triage them before merge. Never merge with an unread\n  Critical/P1. This applies to PRs a skill opened, not just human ones.\n- **Never merge with known findings outstanding.** Fix them on the PR branch; don't\n  merge-then-fix and don't leave them as comments for someone else.\n- **Gate every merge** on the \"Tests (backend + frontend)\" check passing and the PR\n  being `MERGEABLE`.\n- **Always pass an explicit `--body` to `gh pr merge --squash`.** Letting it\n  auto-generate copies every commit message, including any agent\n  `Co-authored-by:` or \"Generated with\" lines, which this repo forbids (see\n  the attribution rule in `CLAUDE.md`).\n- **Check the open-PR queue** before implementing any community-reported fix — a\n  contributor may already have submitted one.\n\n## When a skill says \"publish to the issue tracker\"\n\nCreate a GitHub issue.\n\n## When a skill says \"fetch the relevant ticket\"\n\nRun `gh issue view <number> --comments`.\n\n## Wayfinding operations\n\nUsed by `/wayfinder`. The **map** is a single issue with **child** issues as tickets.\n\n- **Map**: a single issue labelled `wayfinder:map`, holding the Notes / Decisions-so-far / Fog body. `gh issue create --label wayfinder:map`.\n- **Child ticket**: an issue linked to the map as a GitHub sub-issue (`gh api` on the sub-issues endpoint). Where sub-issues aren't enabled, add the child to a task list in the map body and put `Part of #<map>` at the top of the child body. Labels: `wayfinder:<type>` (`research`/`prototype`/`grilling`/`task`). Once claimed, the ticket is assigned to the driving dev.\n- **Blocking**: GitHub's **native issue dependencies** — the canonical, UI-visible representation. Add an edge with `gh api --method POST repos/<owner>/<repo>/issues/<child>/dependencies/blocked_by -F issue_id=<blocker-db-id>`, where `<blocker-db-id>` is the blocker's numeric **database id** (`gh api repos/<owner>/<repo>/issues/<n> --jq .id`, _not_ the `#number` or `node_id`). GitHub reports `issue_dependencies_summary.blocked_by` (open blockers only — the live gate). Where dependencies aren't available, fall back to a `Blocked by: #<n>, #<n>` line at the top of the child body. A ticket is unblocked when every blocker is closed.\n- **Frontier query**: list the map's open children (`gh issue list --state open`, scoped to the map's sub-issues / task list), drop any with an open blocker (`issue_dependencies_summary.blocked_by > 0`, or an open issue in the `Blocked by` line) or an assignee; first in map order wins.\n- **Claim**: `gh issue edit <n> --add-assignee @me` — the session's first write.\n- **Resolve**: `gh issue comment <n> --body \"<answer>\"`, then `gh issue close <n>`, then append a context pointer (gist + link) to the map's Decisions-so-far.\n","AGENTS.md":"## Active desktop: Electron only\n\nElectron (`electron/`) is the only desktop and web UI. The Tauri shell and legacy\nUI entrypoints are removed; do not restore build, runtime, release, or CI paths for\nthem. Triage reports from final Tauri installations toward the migration guide and\npreserve their immutable updater feeds. Some modules under `electron/src/shared/` remain\ntemporarily shared by Electron; they are not a runnable app. New UI, IPC, setup\ninstructions, tests, and browser assets belong in Electron; validate Electron on\nmacOS, Windows and Linux.\n\n## Mobile: native iOS and Android (owner-set 2026-10-17)\n\n`mobile/ios/` (Swift/SwiftUI) and `mobile/android/` (Kotlin/Compose) are native\napps that run models **on the phone** (TTS, dictation, voice cloning, dub\ntranslation; owner-set 2026-10-18) and can also drive a user's own VoiceStudio\ncomputer. Phone first: once models are downloaded they work offline with no\ncomputer; pairing adds the heavy engines, chosen per task. The companion-only\nbuild is the base, not the product. They implement one shared contract,\n`mobile/contract/SPEC.md`: a mobile feature ships on both or neither.\nTheme, API and strings are generated, never hand-copied: `bun\nscripts/export-mobile-tokens.ts` (from the Electron theme), `uv run python\nscripts/export_openapi.py` (from the backend) and the Electron locale catalogs;\n`tests/test_mobile_contract.py` fails on drift. Desktop/web UI still belongs in\nElectron only.\n\n# Agent Rules — VoiceStudio\n\nBinding for every AI agent (Claude, Codex, Cursor, review bots, …). CLAUDE.md is the full constitution; this is the operating contract. When they conflict, CLAUDE.md wins.\n\n## Token economy (owner directive, 2026-07-20; tightened 2026-07-28)\n- **Default to the shortest response that fully answers.** Outlines and tables over prose; no preamble, no recap of what you just did, no re-explaining a fix the diff already shows. Applies to every response, not just status updates.\n- Lead with the outcome. No narration, no restating diffs, no filler praise, no plans you're about to execute anyway.\n- Status updates: one line. Final reports: only what changes the reader's next action.\n- Don't re-derive what CI, linters, or review bots already computed — read their output first (`gh pr checks`, bot comments via `gh api .../pulls/N/comments`).\n- Mechanical rules live in deterministic tests, never in agent effort: changelog style (`tests/test_changelog_style.py`), locale parity (`tests/test_locale_parity.py`), version lockstep (`tests/test_app_version.py`), CJK (`tests/test_no_hardcoded_cjk.py`).\n- Run targeted tests while iterating; full suites only before landing.\n- Tests and CI simulate CI honestly: `HF_HUB_OFFLINE=1` + empty `HF_HUB_CACHE` — a populated dev cache masks real failures.\n\n## Cross-platform parity: behaviour, not performance\n- The parity rule covers user-visible BEHAVIOUR. Hardware acceleration varies by host by design (CUDA/MPS/DirectML, Triton availability, `torch.compile`); skipping an optimization where it physically cannot work is not a parity violation.\n- Do not \"fix\" a parity finding by disabling a working optimization everywhere. That trades a real regression for a semantic one.\n- A feature the user can see and use on one OS but not another IS a violation. Judge by what the user can do, not by how fast it runs.\n\n## Merge protocol (hard rules)\n1. Never merge without review. Harvest CodeRabbit + Greptile comments first; never merge with an unread Critical/P1.\n2. Never accept a PR as-is: fix findings ON the PR branch pre-merge (maintainer commits fine; credit contributors in CHANGELOG). No merge-then-fix, no comment-and-walk-away.\n3. Merge current `main` into stale branches before judging their CI — PR-green under an old workflow ≠ main-green.\n4. Gate: \"Tests (backend + frontend)\" green + MERGEABLE.\n5. After EVERY merge: watch `main`'s own post-merge runs to green (`gh run list --branch main`). Red main = drop everything and fix.\n\n## Change rules (see CLAUDE.md for full text)\n- Root-cause the class, not the instance; fail-before/pass-after regression test; smallest correct change.\n- Default behavior identical on macOS/Windows/Linux; platform-only features go behind explicit opt-in. Divergent default = P0.\n- Local-first: no new required network calls; any HF download gated on installed-ness or explicit user action; all synthetic audio through the `mark_synthetic` chokepoint. Sanctioned calls are listed in `.github/CONTRIBUTING.md` → Quality gates: user-started first-run setup (ffmpeg from GitHub `zackees/ffmpeg_bins`, the huggingface.co/hf-mirror.com reachability probe, HF model downloads), opening/enabling the galleries (jsDelivr manifest, GitHub Releases), packaged update checks, user-clicked yt-dlp updates from PyPI, consent-gated analytics, prefilled-URL bug reports, the Pro licence check after a key is entered, and VoiceStudio Cloud sign-in/account calls (and settings sync once cloud sync is on) only after the user turns them on (off by default; switching off stops them at once). Owner-approved exception (2026-09-28): the public GitHub star count may refresh automatically every 20 minutes, without credentials/referrer or user content; offline use remains unaffected.\n- Every user-facing string via i18n, present in ALL 21 `electron/src/renderer/src/i18n/locales/*.json` files (the catalog the app loads) with real translations; `tests/test_locale_parity.py` and Electron `locale:check` enforce it. The legacy `electron/src/shared/i18n/` catalog is loaded only by shared-module tests.\n- Docs-sync in the same PR. CHANGELOG Unreleased: quiet one-liners ending `(#N)` + `— thanks @user!` for community work, under a short `**Highlights**` list.\n- Tagged release announcements lead with the biggest user-visible change; redesigns need real UI screenshots and migrations need installer links and steps. Verify all contributor credits from the tag comparison and included PRs; list authors and bug reporters separately (see `docs/RELEASING.md`).\n- Versioning: root `package.json` is the single source of truth; never bump without the owner asking.\n- JavaScript dependency changes require regenerating root `bun.lock` (Docker runs `--frozen-lockfile`).\n- Attribution: commits, PR descriptions and comments carry only the submitter's git identity. Never credit an agent (no agent `Co-authored-by:`, \"Generated with …\", session links) and never add other names/emails. Human co-authors are fine. Enforced by the `commit-identity` check.\n- Issues: absorb or decline — never defer to a future version. Check the open-PR queue before implementing community-reported fixes.\n\n## Shared select controls\n\n- Use `electron/src/shared/components/SearchableSelect.jsx` for all new or redesigned select boxes. Reuse `VoiceSelector` for voice choices. Do not introduce native `<select>` controls.\n- Provide a localized `ariaLabel`; use `menuPortal` inside scrolling or clipping containers. Preserve keyboard selection and disabled states.\n\n## Agent skills\n\nProject development skills are pinned in `skills-lock.json` and installed under\n`.agents/skills/`: Vite and FastAPI.\nRepository rules and tracker mappings override generic skill guidance.\n\n### Issue tracker\n\nGitHub Issues on `debpalash/VoiceStudio`, via the `gh` CLI. See `docs/agents/issue-tracker.md`.\n\n### Triage labels\n\nThe five canonical roles, each label string equal to its name. See `docs/agents/triage-labels.md`.\n\n### Domain docs\n\nSingle-context: `docs/adr/` plus a root `CONTEXT.md` that is created lazily and does not exist yet — skip it when absent. See `docs/agents/domain.md`.\n",".claude/skills/omnivoice/LEGACY.md":"# VoiceStudio compatibility entry\n\nThe current cross-agent package is [voicestudio](../../../../skills/voicestudio/SKILL.md).\nFor new installations use `npx skills add debpalash/VoiceStudio --skill voicestudio`.\n\nUse the running backend at the user's configured address (default\n`http://localhost:3900`). Check `/health`, discover `/openapi.json` and\n`/v1/audio/voices`, then use the installed schema for speech, transcription,\nprofiles, and jobs. The HTTP MCP endpoint is `/mcp`; discover tools from the\nconnected server instead of assuming this older package's tool inventory.\n\nLaunch the installed Electron app if the backend is unavailable. For source\ndevelopment follow the checkout's Electron README. Existing helpers in\n`scripts/` support legacy source installations; inspect their environment\nand dependency assumptions before running them.\n\nModel downloads and remote services require the user's choice. Never silently\ninstall models, promise fixed latency, or treat compatibility voice names as\nreal provider voices. Validate saved audio and asynchronous job completion\nbefore reporting success. Protected backends require configured credentials;\nnever disable authentication to make an example work.\n\nSource and current setup documentation:\nhttps://github.com/debpalash/VoiceStudio\n\nThis archived entry is not an installable skill. Existing installations should\nremove the old `omnivoice` / `oss-maintainer` entries and install `voicestudio` /\n`voicestudio-maintainer` from the canonical repository. Legacy helpers remain\nfor existing users; the Electron supervisor is the preferred launcher.\n","tests/evals/suites/dub_translation_naturalness.yaml":"# Suites Skill\n\nPath: `tests/evals/suites/dub_translation_naturalness.yaml`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/tests/evals/suites/dub_translation_naturalness.yaml)",".claude/skills/omnivoice/references/engines-comparison.md":"# References Skill\n\nPath: `.claude/skills/omnivoice/references/engines-comparison.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/references/engines-comparison.md)",".claude/skills/omnivoice/references/mcp-setup.md":"# References Skill\n\nPath: `.claude/skills/omnivoice/references/mcp-setup.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/references/mcp-setup.md)",".claude/skills/omnivoice/scripts/check-health.sh":"# Claude Directive: check-health.sh\n\nPath: `.claude/skills/omnivoice/scripts/check-health.sh`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/scripts/check-health.sh)",".claude/skills/omnivoice/scripts/record-reference.sh":"# Claude Directive: record-reference.sh\n\nPath: `.claude/skills/omnivoice/scripts/record-reference.sh`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/scripts/record-reference.sh)",".claude/skills/omnivoice/scripts/start-backend.sh":"# Claude Directive: start-backend.sh\n\nPath: `.claude/skills/omnivoice/scripts/start-backend.sh`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/scripts/start-backend.sh)",".claude/skills/omnivoice/scripts/stop-backend.sh":"# Claude Directive: stop-backend.sh\n\nPath: `.claude/skills/omnivoice/scripts/stop-backend.sh`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/scripts/stop-backend.sh)"},"files":{".agents/skills/fastapi-python/SKILL.md":"---\nname: fastapi-python\ndescription: Expert in FastAPI Python development with best practices for APIs and async operations\n---\n\n# FastAPI Python\n\nYou are an expert in FastAPI and Python backend development.\n\n## Key Principles\n\n- Write concise, technical responses with accurate Python examples\n- Favor functional, declarative programming over class-based approaches\n- Prioritize modularization to eliminate code duplication\n- Use descriptive variable names with auxiliary verbs (e.g., `is_active`, `has_permission`)\n- Employ lowercase with underscores for file/directory naming (e.g., `routers/user_routes.py`)\n- Export routes and utilities explicitly\n- Follow the RORO (Receive an Object, Return an Object) pattern\n\n## Python/FastAPI Standards\n\n- Use `def` for pure functions, `async def` for asynchronous operations\n- Use type hints for all function signatures. Prefer Pydantic models over raw dictionaries\n- Structure: exported router, sub-routes, utilities, static content, types (models, schemas)\n- Use ordinary Python control flow; prefer readability over compressed one-line conditionals\n\n## Error Handling\n\n- Handle edge cases at function entry points\n- Employ early returns for error conditions\n- Place happy path logic last\n- Avoid unnecessary else statements; use if-return patterns\n- Implement guard clauses for preconditions\n- Provide proper error logging and user-friendly messaging\n\n## FastAPI-Specific Guidelines\n\n- Use functional components (plain functions) and Pydantic models for input validation\n- Declare routes with clear return type annotations\n- Prefer lifespan context managers for managing startup and shutdown events\n- Leverage middleware for logging, error monitoring, and optimization\n- Use HTTPException for expected errors and model them as specific HTTP responses\n- Apply Pydantic's BaseModel consistently for validation\n\n## Performance Optimization\n\n- Minimize blocking I/O. In `async def` handlers, use awaitable database/API clients; put synchronous SQLite or other blocking work in synchronous routes or explicitly offload it\n- Implement caching with Redis or in-memory stores\n- Optimize Pydantic serialization/deserialization\n- Use lazy loading for large datasets\n\n## Key Conventions\n\n1. Rely on FastAPI's dependency injection system\n2. Prioritize API performance metrics (response time, latency, throughput)\n3. Structure routes and dependencies for readability and maintainability\n\n## Dependencies\n\nFastAPI, Pydantic v2, asyncpg/aiomysql, SQLAlchemy 2.0\n",".agents/skills/vite/SKILL.md":"---\nname: vite\ndescription: Expert guidance for Vite development with modern build tooling, HMR, framework integrations, and performance optimization\n---\n\n# Vite Development\n\nYou are an expert in Vite, modern JavaScript/TypeScript build tooling, and frontend development.\n\n## Key Principles\n\n- Leverage native ES modules for fast development\n- Use Vite's opinionated defaults when possible\n- Configure only what needs customization\n- Understand the dev/build differences\n- Optimize for both development speed and production performance\n\n## Project Setup\n\n### Basic Configuration\n```typescript\n// vite.config.ts\nimport { defineConfig } from 'vite';\nimport react from '@vitejs/plugin-react';\n\nexport default defineConfig({\n  plugins: [react()],\n  server: {\n    port: 3000,\n    open: true,\n  },\n  build: {\n    outDir: 'dist',\n    sourcemap: true,\n  },\n});\n```\n\n### Path Aliases\n```typescript\nimport { defineConfig } from 'vite';\n\nexport default defineConfig({\n  resolve: {\n    alias: {\n      '@': new URL('./src', import.meta.url).pathname,\n      '@components': new URL('./src/components', import.meta.url).pathname,\n      '@utils': new URL('./src/utils', import.meta.url).pathname,\n    },\n  },\n});\n```\n\n## Environment Variables\n\n### Usage\n```typescript\n// .env\nVITE_API_URL=https://api.example.com\nVITE_APP_TITLE=My App\n\n// In code\nconst apiUrl = import.meta.env.VITE_API_URL;\nconst isDev = import.meta.env.DEV;\nconst isProd = import.meta.env.PROD;\nconst mode = import.meta.env.MODE;\n```\n\n### Type Definitions\n```typescript\n// src/vite-env.d.ts\n/// <reference types=\"vite/client\" />\n\ninterface ImportMetaEnv {\n  readonly VITE_API_URL: string;\n  readonly VITE_APP_TITLE: string;\n}\n\ninterface ImportMeta {\n  readonly env: ImportMetaEnv;\n}\n```\n\n## Hot Module Replacement\n\n### Manual HMR\n```typescript\n// For libraries without HMR support\nif (import.meta.hot) {\n  import.meta.hot.accept('./module.ts', (newModule) => {\n    // Handle the updated module\n    console.log('Module updated:', newModule);\n  });\n\n  import.meta.hot.dispose(() => {\n    // Cleanup before module is replaced\n  });\n}\n```\n\n## Asset Handling\n\n### Static Assets\n```typescript\n// Import as URL\nimport imageUrl from './image.png';\n// <img src={imageUrl} />\n\n// Import as string (raw)\nimport shaderCode from './shader.glsl?raw';\n\n// Import as worker\nimport Worker from './worker.ts?worker';\nconst worker = new Worker();\n```\n\n### Public Directory\n```\npublic/\n├── favicon.ico      # Served at /favicon.ico\n├── robots.txt       # Served at /robots.txt\n└── images/          # Served at /images/\n```\n\n## Framework Integrations\n\n### React\n```typescript\nimport { defineConfig } from 'vite';\nimport react from '@vitejs/plugin-react';\n\nexport default defineConfig({\n  plugins: [\n    react({\n      // Babel plugins\n      babel: {\n        plugins: ['@emotion/babel-plugin'],\n      },\n    }),\n  ],\n});\n```\n\n### Vue\n```typescript\nimport { defineConfig } from 'vite';\nimport vue from '@vitejs/plugin-vue';\n\nexport default defineConfig({\n  plugins: [vue()],\n});\n```\n\n### Svelte\n```typescript\nimport { defineConfig } from 'vite';\nimport { svelte } from '@sveltejs/vite-plugin-svelte';\n\nexport default defineConfig({\n  plugins: [svelte()],\n});\n```\n\n## Build Optimization\n\n### Code Splitting\n```typescript\n// Dynamic imports create separate chunks\nconst AdminPanel = lazy(() => import('./AdminPanel'));\n\n// Manual chunks\nexport default defineConfig({\n  build: {\n    rollupOptions: {\n      output: {\n        manualChunks: {\n          vendor: ['react', 'react-dom'],\n          utils: ['lodash', 'date-fns'],\n        },\n      },\n    },\n  },\n});\n```\n\n### Chunk Size Optimization\n```typescript\nexport default defineConfig({\n  build: {\n    chunkSizeWarningLimit: 500,\n    rollupOptions: {\n      output: {\n        manualChunks(id) {\n          if (id.includes('node_modules')) {\n            return id.split('node_modules/')[1].split('/')[0];\n          }\n        },\n      },\n    },\n  },\n});\n```\n\n## CSS Handling\n\n### CSS Modules\n```typescript\n// styles.module.css is auto-detected\nimport styles from './styles.module.css';\n\n// <div className={styles.container}>\n```\n\n### PostCSS\n```javascript\n// postcss.config.js\nexport default {\n  plugins: {\n    tailwindcss: {},\n    autoprefixer: {},\n  },\n};\n```\n\n### Preprocessors\n```typescript\n// Automatically handled with package installed\n// npm install -D sass\nimport './styles.scss';\n```\n\n## Proxy Configuration\n\n```typescript\nexport default defineConfig({\n  server: {\n    proxy: {\n      '/api': {\n        target: 'http://localhost:4000',\n        changeOrigin: true,\n        rewrite: (path) => path.replace(/^\\/api/, ''),\n      },\n      '/socket.io': {\n        target: 'ws://localhost:4000',\n        ws: true,\n      },\n    },\n  },\n});\n```\n\n## Plugin Development\n\n```typescript\n// my-vite-plugin.ts\nimport type { Plugin } from 'vite';\n\nexport function myPlugin(): Plugin {\n  return {\n    name: 'my-plugin',\n\n    // Hook: modify config\n    config(config, { mode }) {\n      return {\n        define: {\n          __BUILD_TIME__: JSON.stringify(new Date().toISOString()),\n        },\n      };\n    },\n\n    // Hook: transform code\n    transform(code, id) {\n      if (id.endsWith('.md')) {\n        return {\n          code: `export default ${JSON.stringify(code)}`,\n          map: null,\n        };\n      }\n    },\n\n    // Hook: configure dev server\n    configureServer(server) {\n      server.middlewares.use((req, res, next) => {\n        // Custom middleware\n        next();\n      });\n    },\n  };\n}\n```\n\n## Testing with Vitest\n\n```typescript\n// vitest.config.ts\nimport { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  test: {\n    globals: true,\n    environment: 'jsdom',\n    setupFiles: './src/test/setup.ts',\n    coverage: {\n      provider: 'v8',\n      reporter: ['text', 'json', 'html'],\n    },\n  },\n});\n```\n\n## SSR Configuration\n\n```typescript\nexport default defineConfig({\n  build: {\n    ssr: true,\n    rollupOptions: {\n      input: './src/entry-server.ts',\n    },\n  },\n  ssr: {\n    external: ['express'],\n    noExternal: ['my-ui-library'],\n  },\n});\n```\n\n## Library Mode\n\n```typescript\nexport default defineConfig({\n  build: {\n    lib: {\n      entry: './src/index.ts',\n      name: 'MyLib',\n      fileName: (format) => `my-lib.${format}.js`,\n    },\n    rollupOptions: {\n      external: ['react', 'react-dom'],\n      output: {\n        globals: {\n          react: 'React',\n          'react-dom': 'ReactDOM',\n        },\n      },\n    },\n  },\n});\n```\n\n## Best Practices\n\n- Use `vite preview` to test production builds locally\n- Keep dependencies that support ESM in regular deps\n- Use `optimizeDeps.include` for CommonJS dependencies\n- Enable `build.sourcemap` for debugging production\n- Use `server.warmup` for faster dev server starts\n","skills/voicestudio-maintainer/SKILL.md":"---\nname: voicestudio-maintainer\ndescription: Triage GitHub issues, review contributor pull requests, diagnose CI, and prepare explicitly requested releases for VoiceStudio's Electron desktop app and Python backend. Use for repository maintenance work, not ordinary VoiceStudio audio generation.\n---\n\n# VoiceStudio maintenance\n\nRead the target repository's AGENTS.md, CLAUDE.md, contribution guide, and release documentation first. Their policies override this general workflow. Installing this skill does not authorize merges, releases, issue closures, or messages to contributors.\n\n## Triage and implementation\n\n- Inspect current code and existing PRs before duplicating a reported fix. Reuse contributor work where it solves the problem; retain attribution.\n- Reproduce the reported behavior where possible. Separate confirmed failures from diagnosis, and record meaningful limitations in the PR.\n- Fix the cause with the smallest complete change. Test observable behavior where it can regress; do not mistake a source-text assertion for an end-to-end test.\n- Preserve local changes. Use an isolated worktree when branch switching would disturb them.\n- Read existing CI failures and reviewer comments before rerunning work. Diagnose failures before retries; never hide a failing gate behind a successful piped command.\n- Keep user-facing docs and required translations aligned with the implementation.\n\n## Review and authorized landing\n\nReview the current diff, bot findings, and required checks against current main. Resolve material findings on the PR branch before landing; do not merge first and promise a follow-up. Refresh stale branches using the repository's policy and preserve contributor commits.\n\nBefore an authorized merge, verify required checks are green, the head has not changed, and the PR is mergeable. After landing, inspect main's own runs; investigate regressions immediately. Report remaining blockers without inventing a successful verification.\n\n## Release preparation\n\nPreparing CI or packaging is distinct from publishing. Do not tag, bump versions, enable publishing, or cut a release unless that action is authorized.\n\nUse the repository's version source of truth, changelog format, supported platforms, and distribution channels. Validate packaging and workflows without publishing when that is the requested scope. After an authorized release, verify actual artifacts, release notes, updater metadata, and requested registry channels; a green build alone does not prove distribution.\n\n## Communication\n\nLead with the outcome and evidence. Credit concrete contributor work. Do not close stale issues merely because of age, or claim reporter confirmation that has not occurred. For authorized closures, give the resolution and what evidence would justify reopening.\n\n## VoiceStudio-specific routing\n\nWhen maintaining debpalash/VoiceStudio, consult its current rules rather than old architecture assumptions:\n- Electron development and packaging: `electron/README.md`, `electron/package.json`, and `.github/workflows/`.\n- Backend contracts: running `/openapi.json`, `backend/api/`, and targeted tests.\n- Release channels and version ownership: `docs/RELEASING.md` and CLAUDE.md. Never infer a version bump from a fix request.\n- Read CodeRabbit/Greptile findings and required CI before merging. Follow main's post-merge CI.\n- Preserve local-first behavior, cross-platform behavior, model-install consent, synthetic-audio marking, and localization requirements.\n\n## Current development commands\n\nRun from the repository root:\n\n```sh\nbun install\nbun run setup:api        # prepare the source Python runtime explicitly\nbun run dev              # Electron + supervised backend\nbun run typecheck        # Electron main, preload, and renderer\nbun run test             # Electron tests\nbun run check:electron   # types, tests, build, packaging contract\nbun run dist             # local installers; publishing disabled\n```\n\n`electron/src/main/` owns lifecycle, IPC, native helpers, and backend supervision;\n`electron/src/preload/` exposes the renderer bridge; `electron/src/renderer/src/`\ncontains the React app. Keep privileged filesystem/process work out of the renderer.\n`electron/src/shared/` holds modules shared with the browser build; it is not a\nrunnable app. `backend/` supplies the shared Python API; `native/desktop-bridge/`\nsupplies native capabilities. `frontend/` only receives the browser build output\n(`bun run build:web` → `frontend/dist/`, served by the backend in Docker). Do not\nrename internal `omnivoice` packages, environment keys, or data paths as a\nbranding cleanup.\n\nElectron is the only desktop app and web UI. The Tauri shell is removed; do not\nrestore it. Its final v0.5.3 updater feeds are immutable compatibility assets,\nand old Tauri installs move over with `docs/electron-migration.md`.\nUse `electron-build.yml` for artifact-only packaging rehearsals; inspect its\nresults for Windows x64, Linux, macOS Intel, and macOS Apple Silicon (Windows\nARM64 is an experimental leg that may fail without blocking).\nDo not dispatch release/publishing workflows to test packaging. Signing, updater\nmigration, and successful installation are separate checks from a green build.\nThe app version comes from the root `package.json` (mirrored in `pyproject.toml`\nand `backend/core/version.py`); do not bump it without an explicit versioning task.\n\nFor backend tests, use the repo's CI dependencies and an empty temporary\n`HF_HUB_CACHE` with `HF_HUB_OFFLINE=1`; installed developer models must not hide\nmissing fixtures. Run targeted tests while editing and the required full checks\nbefore landing. Existing CI failures remain blockers, not implied waivers.\n","skills/voicestudio/SKILL.md":"---\nname: voicestudio\ndescription: Generate local speech with saved or designed voices, transcribe audio, and automate dubbing or narration workflows through VoiceStudio's REST API or MCP server. Use when the user wants to work with VoiceStudio audio or connect it to an agent or automation.\n---\n\n# VoiceStudio\n\nUse the user's running [VoiceStudio](https://github.com/debpalash/VoiceStudio) backend. Prefer local processing; cloud translation, model downloads, remote-backend connections, and external integrations require the user's choice. Installed models can run offline; do not promise that every configured workflow is offline.\n\n## Connect and discover\n\nThe default backend is `http://localhost:3900`; honor the user's configured address. Electron's renderer and development proxy are separate services, not the public backend API.\n\n1. Check `GET /health`.\n2. Discover the running version's contracts with `GET /openapi.json`, and voices/engines with `GET /v1/audio/voices`. Do not invent profile IDs or infer installed models from a catalog listing.\n3. If unavailable, launch the installed app. For an existing source checkout, follow its Electron README (`bun install`, `bun run setup:api`, then `bun run dev` from the repository root). Do not install a second backend or overwrite an existing checkout.\n4. Local configurations may permit unauthenticated calls; protected deployments require the configured credentials. Treat 401/403 as authentication failures, not permission to disable auth. Never print tokens or use a placeholder key as if it were a real credential.\n\n## Generate speech\n\nSave this JSON to `speech-request.json`, replacing `voice` with a discovered profile ID when the user selected a voice:\n\n```json\n{\"model\":\"tts-1\",\"voice\":\"alloy\",\"input\":\"Every voice has a story. Let's tell yours.\",\"response_format\":\"wav\"}\n```\n\n```sh\ncurl --fail-with-body --show-error http://localhost:3900/v1/audio/speech \\\n  -H 'Content-Type: application/json' --data-binary @speech-request.json \\\n  --output speech.wav\n```\n\n`tts-1` and `tts-1-hd` are aliases, not quality guarantees. OpenAI voice names are compatibility aliases, not those providers' actual voices. Prefer a discovered saved voice for repeatable narration. Check the installed engine's language and voice-design capabilities before promising a result.\n\nCheck the HTTP status and decode/probe the output before calling it audio: an error response can be written to the output path. Report the saved path and actual duration/format. Never fabricate a successful generation, transcript, or job completion.\n\n## Transcribe\n\n```sh\ncurl --fail-with-body --show-error http://localhost:3900/v1/audio/transcriptions \\\n  -F file=@clip.wav -F model=whisper-1 -F response_format=verbose_json\n```\n\nUse `json` or `text` for plain transcripts, `verbose_json` for timestamps, and `srt`/`vtt` for subtitles when supported by the running schema. Check transcription-model readiness before long recordings; explain a missing model and obtain download authorization rather than silently installing it.\n\n## Cloning, design, dubbing, and longer workflows\n\nUse the installed OpenAPI schema to discover profile creation, reference uploads, generation, dubbing, and long-form job operations. Their native endpoints are broader than the OpenAI compatibility API and evolve independently.\n\n- Clone only voices the user is authorized to use. Preserve reference files and existing profiles.\n- For design, capture the requested tone, delivery, language, and sample text; check engine support.\n- For dubbing, retain original media, speaker assignments, segment timing, and background-audio intent. Translation completion is not rendered-dub completion.\n- For asynchronous work, use returned job IDs and documented progress/status endpoints. Inspect terminal errors; avoid blindly resubmitting timed-out generation.\n- Return usable files and honest limitations, including missing models or unavailable capabilities.\n\n## MCP and automation\n\nThe running backend mounts an MCP endpoint at `http://localhost:3900/mcp`. Use the client's supported HTTP transport and discover its tools at runtime. Reuse an existing connection rather than spawning another service. For stdio-only clients, consult the project's [MCP guide](https://github.com/debpalash/VoiceStudio/blob/main/docs/mcp.md) for its shim.\n\nFor n8n, calling agents, containers, or other hosts, make the backend address reachable from that environment: container `localhost` refers to the container. Keep authentication and explicit remote-routing choices intact. An integration-directory listing does not mean the integration is connected.\n\nOn errors, read the response body, distinguish unavailable backend, missing model, unsupported capability, authentication, and busy hardware. Fix the reported condition; do not switch to a hosted provider or download a model without authorization.\n\n## Desktop workflows and readiness\n\nThe Electron app includes voice cloning and design, saved profiles and gallery,\nstories/audiobooks, dubbing projects, transcription, tools, and integrations.\nPrefer its existing project and voice identifiers over creating duplicates.\nFor desktop automation, inspect the actual UI and current Settings shortcuts;\ndo not assume shortcut bindings or microphone permissions are the same on every host.\n\nBefore dictation, verify an installed speech-to-text model and a working input\ndevice. Distinguish recording, paused recording, transcription processing, and\ncompleted text. Copying a transcript and inserting it into another app are different\noperations; confirm the intended target before typing and preserve clipboard content\nwhere supported. Never report text delivered just because transcription completed.\n\nFor dubbing, inspect missing/failed segments and timing overflow before export.\nPreserve music and non-speech audio when requested; do not silently replace the\nwhole soundtrack. Preserve the source and make the output a separate artifact.\nTranslation style prompts belong to the selected translation operation, and remote\nagent translation requires the user's configured provider choice.\n\nUse the integrations directory as discovery and setup guidance, not proof of a\nworking connector. Verify actual credentials, endpoint reachability, and supported\noperations before describing a connection as ready. Container deployments need\npersistent data volumes and a backend URL reachable by the calling client.\n","CLAUDE.md":"## Active desktop: Electron only\n\nElectron (`electron/`) is the only desktop and web UI. The Tauri shell and legacy\nUI entrypoints are removed; do not restore build, runtime, release, or CI paths for\nthem. Triage reports from final Tauri installations toward the migration guide and\npreserve their immutable updater feeds. Some modules under `electron/src/shared/` remain\ntemporarily shared by Electron; they are not a runnable app. New UI, IPC, setup\ninstructions, tests, and browser assets belong in Electron; validate Electron on\nmacOS, Windows and Linux.\n\n## Mobile: native iOS and Android (owner-set 2026-10-17)\n\n`mobile/ios/` (Swift/SwiftUI) and `mobile/android/` (Kotlin/Compose) are native\napps that run models **on the phone** (TTS, dictation, voice cloning, dub\ntranslation; owner-set 2026-10-18) and can also drive a user's own VoiceStudio\ncomputer. Phone first: once models are downloaded they work offline with no\ncomputer; pairing adds the heavy engines, chosen per task. The companion-only\nbuild is the base, not the product. They implement one shared contract,\n`mobile/contract/SPEC.md`: a mobile feature ships on both or neither.\nTheme, API and strings are generated, never hand-copied: `bun\nscripts/export-mobile-tokens.ts` (from the Electron theme), `uv run python\nscripts/export_openapi.py` (from the backend) and the Electron locale catalogs;\n`tests/test_mobile_contract.py` fails on drift. Desktop/web UI still belongs in\nElectron only.\n\n<!-- GSD:project-start source:PROJECT.md -->\n## Project\n\n**VoiceStudio**\n\nVoiceStudio is an open-source, fully-local ElevenLabs alternative — a desktop app for voice cloning, voice design, video dubbing, and real-time dictation across 646 languages. It runs entirely on the user's machine (CUDA/MPS/ROCm/CPU auto-detect), with no API keys, no accounts, and no cloud dependencies. It's an active beta with a growing user base who hit it with real workloads (50-video batches, multi-engine setups, edge-OS platforms) and report friction in GitHub Issues and Discord. The current version lives in the root `package.json` (the single source of truth — see Versioning); the latest stable tag is on the [Releases page](https://github.com/debpalash/VoiceStudio/releases/latest). With `AUTO_VERSION_BUMP` off (the current owner setting), `main` holds at the released version between releases.\n\n**Core Value:** **A first-run that actually works.** A user who downloads the installer (or clones the repo) should reach a working voice-cloning or dubbing output without hitting a wall — and when something does go wrong, the error or docs should tell them exactly what to do.\n\nEverything else (new engines, fancy features) is downstream of \"the thing installs and runs reliably across platforms, with the engines and pipelines users already depend on staying compatible.\"\n\n### Constraints\n\n- **Existing engine compatibility**: Users with already-installed engines (IndexTTS, CosyVoice, etc.) must not have to reinstall. Fixes touching engine code must be backward-compatible with on-disk model state.\n- **Cross-platform parity**: Every fix must work on macOS (Apple Silicon; Intel Macs are limited to the app UI with a remote backend, as README.md and `docs/install/macos.md` document), Windows (x64), and Linux (AppImage + deb). No platform-only regressions; the cross-platform bug bash (PR #51) is the baseline.\n- **Default features must work on every platform (strict rule, 2026-05-20):** A feature that ships in default mode — out-of-the-box, no user customization, no opt-in toggle — must behave identically on macOS, Windows, and Linux. Platform-specific *implementation code* is allowed for OS APIs / shells / packaging, but the user-visible *default behavior* cannot diverge. Platform-only features (e.g., a macOS-only global shortcut, a Windows-only path picker) must go behind explicit user opt-in: Settings toggle, env var, or CLI flag. When a default doesn't work on a platform, that's a P0 bug — either fix it on the missing platform or move it behind opt-in. No third option. **This rule governs BEHAVIOUR, not PERFORMANCE** (clarified 2026-07-30, council): hardware acceleration is expected to vary by host — CUDA, MPS, DirectML, Triton availability and `torch.compile` are all host-dependent by design, and reading the rule to forbid that would forbid GPU support itself. An optimization that is skipped where it cannot work (missing Triton, an arch the wheel lacks, a path its toolchain cannot link) is NOT a parity violation; a *feature* the user can see and use on one OS but not another is.\n- **Backward-compatible project data**: Existing `omnivoice_data/` (user voices, projects, settings) must keep working without manual migration. Any DB schema change goes through alembic with a tested upgrade path.\n- **Local-first guarantee preserved**: nothing leaves the machine without the user's **explicit yes**, and the app must remain fully functional with everything declined. Auto bug reporting is opt-in and submits only to GitHub Issues (prefilled-URL, from the user's own browser). Product analytics (owner-sanctioned 2026-07-16; US project migration 2026-09-26) is opt-in PostHog US with a **first-run consent prompt** — two equal-weight Yes/No buttons, never default-on, skipping = off; consent-gated, allowlisted content-free metadata only (`backend/core/analytics.py`); every build — installer, Docker, and source alike (owner reversal 2026-07-20, #1193) — carries the in-repo publishable write-only token and shows the same consent ask, with env/baked token overriding it. No required cloud calls, accounts, or API keys. Sanctioned calls (owner-set 2026-10-02; full list in `.github/CONTRIBUTING.md` → Quality gates): during first-run setup the user starts — the pinned ffmpeg download from GitHub `zackees/ffmpeg_bins` (`backend/services/media_tools.py`), the huggingface.co/hf-mirror.com reachability probe for restricted networks (`backend/services/endpoint_race.py`), and Hugging Face model downloads; opening the community gallery (jsDelivr manifest, `backend/api/routers/community.py`) or enabling the voice-preview gallery (GitHub Releases, `backend/services/gallery.py`); packaged update checks against GitHub Releases (`electron/src/main/updater.ts`); yt-dlp updates from PyPI when the user clicks update; and, only after the user turns account features on (first-run setup or Settings → Account, off by default), VoiceStudio Cloud sign-in and account calls from Electron main (`electron/src/main/account/`), plus settings sync from the backend (`backend/services/cloud_sync/`) once cloud sync is also on, all stopped at once when switched off. Narrow owner-approved exception (2026-09-28): the GitHub Star badge may fetch the public repository star count when shown and refresh every 20 minutes while visible, without credentials or a referrer. It sends no project, recording, or account data, retains the last count on failure, and never blocks offline use.\n- **Beta release cadence (no RC, no ceremony — strict rule, 2026-05-20):** the current release line (0.5.x today) has **no release candidates, no 48h soak, no formal release ceremony**. Every fix goes continuous-to-main; the owner tags a patch from main whenever the current state is worth cutting. No `-rc` tags. No phased release. The one sanctioned prerelease is the opt-in **Beta channel** (owner-approved 2026-10-22): `vX.Y.Z-beta.N` tags cut from `main`, published as GitHub prereleases that never become `latest`, with their own `electron-beta-*` update feed and `:beta` Docker tag (see `docs/RELEASING.md` → Beta channel). It adds no soak, ceremony or side branch. No deferrals to a future minor or major version — every open issue and every open community PR gets absorbed into the current line or explicitly declined. Users follow `main` for previews; users wanting stable stay on the latest tagged release.\n<!-- GSD:project-end -->\n\n<!-- GSD:stack-start source:research/STACK.md -->\n## Technology Stack\n\nThe May-2026 stack research that used to live here served five capabilities that have all since shipped (HF-token Settings panel, prefilled-URL bug reporting, uv mirror fallback for restricted networks, the Supertonic-3 engine, in-repo Markdown docs). Follow the patterns in the code itself; the durable *don'ts* that research established:\n\n- **No third-party endpoints for bug reporting or crash dumps** (`sentry-tauri` was evaluated and rejected) — bug reporting stays opt-in via prefilled GitHub-issue URLs, submitted from the user's own browser. The one sanctioned third-party endpoint is the opt-in PostHog US product analytics and error tracking (owner-set 2026-07-16; migrated 2026-09-26; sanitized renderer errors approved 2026-09-26), which is consent-gated behind the first-run prompt and ships allowlisted content-free metadata only. Raw exception, DOM, and session autocapture stay disabled; manually captured renderer exceptions must replace messages and scrub stack paths before transmission. Its publishable write-only project token is committed in-repo (owner reversal 2026-07-20, #1193 — source builds get the same consent-gated analytics as installers; env/baked token overrides), allowed by `tests/test_no_committed_analytics_token.py` in exactly `backend/core/analytics.py` + `electron/src/shared/utils/analytics.ts`.\n- **No PAT/token-based GitHub posting from the app** — the user submits from their own browser.\n- **Don't recommend `setx` for env vars on Windows** (silent truncation, no current-shell propagation) — use the in-app Settings panel or PowerShell `[Environment]::SetEnvironmentVariable`.\n- **Don't adopt Material for MkDocs** for any future docs site (maintenance mode since Nov 2025) — Astro Starlight is the precedent if docs ever outgrow the repo.\n- **`hf_transfer` is deprecated** — default `huggingface_hub` (hf-xet) handles downloads.\n\nFor anything new: prefer what's already pinned in `pyproject.toml` / `electron/package.json`, and check `uv tree` for conflicts before adding a dependency.\n<!-- GSD:stack-end -->\n\n<!-- GSD:conventions-start source:CONVENTIONS.md -->\n## Conventions\n\n**Versioning (hard rule, owner-set 2026-06-11; single-source 2026-09-26):** **The root `package.json` is the SINGLE SOURCE OF TRUTH for the maintained Electron app version** — Electron's builder reads it directly and Vite injects `__APP_VERSION__` for the UI and bug reports. Two toolchain-required **mirrors** are kept equal to it and bumped in lockstep: `pyproject.toml` and `backend/core/version.py`'s `_FALLBACK_VERSION`. Guarded by `tests/test_app_version.py`. Version bumps are manual and happen only when the owner asks; until then, `main` may equal the latest released version. Consequences:\n- Every PR and preview build uses the canonical version. Preview artifacts add the workflow run number without changing the checked-in version.\n- Releasing = obtain owner approval for the version, bump the canonical version and maintained mirrors together, then tag that exact version from `main` after validation.\n- Docker: `ghcr.io/debpalash/voicestudio:latest` = **main** (rolling preview); `:X.Y.Z` + `:X.Y` + `:stable` = tagged releases; `:beta` + `:X.Y.Z-beta.N` = beta prereleases (never `:stable`/`:X.Y`). `:latest` is the preview channel by design — stable users pin `:stable` or a version tag. The former `ghcr.io/debpalash/omnivoice-studio` coordinate remains a compatibility alias.\n- Do not bump minor/major or invent RCs/codenames without the owner asking. A beta version (`X.Y.Z-beta.N`) is bumped in the same three places, only when the owner asks, and uses the same lockstep. No \"defer to next version\" labels — scope is absorbed or declined, never re-versioned.\n\n**Docs-sync (hard rule, owner-set 2026-06-11):** any change that alters something these docs describe — README.md, `.github/CONTRIBUTING.md`, `.github/SECURITY.md`, `.github/SUPPORT.md`, LICENSE, or `docs/**` (install flows, Docker tag semantics, platform support, versioning/release behavior, review process, supported versions) — must update those docs **in the same PR** as the change. If a doc impact is discovered after merge, the docs fix is the immediate next commit, not backlog. Stale docs are treated as bugs.\n\n**Release notes / changelog (hard rule, owner-set 2026-06-16):** every tagged release gets a **high-quality, user-facing `## [X.Y.Z] — DATE` section in `CHANGELOG.md`** before (or in the same hour as) the tag — never the \"Auto-generated release for vX.Y.Z…\" fallback. The desktop release workflow extracts that section verbatim as the GitHub Release body, so a missing/empty section ships a bare release. Quality bar (owner-restyled 2026-07-17, replaces the old bold-lead paragraphs): **quiet and scannable change entries** — after an optional tagged-release introduction (see the presentation rule below), a short `**Highlights**` bullet list (plain words, one line each), then `### Changed` / `### Added` / `### Docs` / `### Fixed` / `### License` / `### CI` subsections where each entry is a **single one-liner** with the `(#NNN)` issue/PR ref and contributor credit (`— thanks @user!`) where applicable. Change entries are written for users, grouped by theme, with no multi-line entry paragraphs or raw commit dumps. This applies to **preview builds too**: preview release notes summarize what's new on `main` since the last stable, in the same style. Workflow: as features merge, keep `## [Unreleased]` current; at release time rename it to the version + date. If a release was already cut with the fallback body, the next action is to backfill `CHANGELOG.md` **and** `gh release edit <tag>` the live body — not backlog.\n\n**Release presentation and credits (owner-set 2026-09-17):** Tagged release announcements lead with the biggest user-visible change; redesigns need real UI screenshots and migrations need installer links and steps. Verify all contributor credits from the tag comparison and included PRs; list authors and bug reporters separately (see `docs/RELEASING.md`). Keep Highlights to 3–5 bullets; the release introduction can include prose, images, and a download table before the concise change entries.\n\n**Localization (hard rule):** No hardcoded non-English (CJK) **user-facing text** anywhere in the codebase except the translation layers: `electron/src/renderer/src/i18n/` (the catalog the app loads; checked by `tests/test_locale_parity.py` and Electron `locale:check`) and the legacy `electron/src/shared/i18n/` (loaded only by shared-module tests). All UI strings go through i18n (`t('...')` keys in `locales/*.json`); native language names live in `i18n/index.ts` (`LANGUAGES`). Functional CJK is allowed and tracked via the allowlist in `tests/test_no_hardcoded_cjk.py` — text-processing regexes, model/engine vocabulary & identifiers (e.g. CosyVoice speaker IDs), localized error matching, demo/eval data, and test fixtures. CI fails on any hardcoded CJK outside the allowlist; to add legitimate functional CJK, extend `_ALLOWED_FILES` there with a justification.\n\n**Release deployment channels (hard rule, owner-set 2026-07-16):** a version bump is not \"released\" until **every** maintained channel ships it — the full checklist lives in `docs/RELEASING.md`. The channels are the Electron GitHub Release (Linux x64, Windows x64 + experimental ARM64, macOS arm64 + x64), GHCR and Docker Hub in CUDA and ROCm flavors, and the Docker Hub overview page synced from `deploy/dockerhub-overview.md`. The final Tauri feeds are immutable compatibility assets copied into releases for old clients; they are never rebuilt. Verify all channels after tagging. Preview/RC builds always source from `main`; never cut a side-branch build.\n\n**Fix quality (hard rule, owner-set 2026-06-16):** Fix issues *properly* and future-maintenance-proof — don't stop at the symptom. Root-cause fully, fix the whole **class** of the bug (not just the one reported instance), add a fail-before/pass-after regression test, and harden against recurrence (e.g. if a lockfile drift only fails in Docker, also make CI catch it). Go the extra mile where it durably pays off. Be token-efficient about it — extra **effort**, not extra **verbosity**: no padding, no redundant re-checks, the smallest correct change that is also recurrence-proof. Don't be shy to spend the effort a proper fix needs; do be shy about wasting tokens.\n\n**Keep main green (hard rule, owner-set 2026-06-16):** A merge must **never break `main`'s CI**. Before a change lands, verify the *full* active CI matrix and `deploy/Dockerfile`, not only the checks you happened to run. Dependency / lockfile / config changes must be validated against all maintained consumers. The lockfile is the repo-root `bun.lock`; any workspace package change requires regenerating it and confirming `bun install --frozen-lockfile` passes. Re-check CodeQL/Security on code changes and the Electron native helper on Rust changes. Do not use the archived Tauri build as a gate.\n\nOther conventions not yet established. Will populate as patterns emerge during development.\n**Attribution and identity (hard rule, owner-set 2026-10-02):** commits, PR descriptions, and issue/PR comments carry only the submitter's own git identity. AI agents are never credited: no agent `Co-authored-by:` trailer, no \"Generated with …\" line, no session links, no agent author/committer. Never put names or emails other than the configured git identity into commits or comments (no personal emails, no placeholder identities). Human co-authors are fine. Enforced on PRs by `scripts/check_commit_identities.py` (the `commit-identity` check).\n\n<!-- GSD:conventions-end -->\n\n<!-- GSD:architecture-start source:ARCHITECTURE.md -->\n## Architecture\n\nArchitecture not yet mapped. Follow existing patterns found in the codebase.\n<!-- GSD:architecture-end -->\n\n<!-- GSD:skills-start source:skills/ -->\n## Project Skills\n\n- `vite` — Vite configuration, assets, HMR, builds, and Vitest guidance.\n- `fastapi-python` — FastAPI and Pydantic implementation patterns.\n\nCanonical copies live under `.agents/skills/`; `skills-lock.json` pins their sources and hashes. Claude should follow these paths directly, avoiding cross-platform symlinks.\n<!-- GSD:skills-end -->\n\n<!-- GSD:workflow-start source:GSD defaults -->\n## Workflow\n\nDirect repo edits are authorized (owner decision, 2026-07-08). The GSD command gate that used to live here referenced `/gsd-quick` / `/gsd-debug` / `/gsd-execute-phase` skills that are not installed in this environment; the owner chose to keep working directly rather than restore them. The working conventions that matter are in **Conventions** above — versioning, docs-sync, changelog, localization, fix quality, keep-main-green — plus: gate every merge on the \"Tests (backend + frontend)\" check passing and the PR being MERGEABLE, and check the open-PR queue before implementing any community-reported fix (contributors may have already submitted one).\n\n**Harvest bot reviews before merging (rule, 2026-07-20):** CodeRabbit and Greptile auto-review every PR (tuned via `.coderabbit.yaml` / `greptile.json`, both fed CLAUDE.md as context). Before merging ANY PR — including your own — read their inline comments (`gh api repos/<owner>/<repo>/pulls/<N>/comments` filtered by bot login) and triage: fix real findings, ignore noise, never merge with an unread Critical/P1. They are the free first review pass; reserve deep agent-driven review for what they can't judge (architecture, cross-file semantics, product intent). Mechanical rules belong in deterministic CI tests, not in any AI reviewer.\n\n**Token economy (owner directive, 2026-07-20; tightened 2026-07-28):** default to the shortest response that fully answers — outlines and tables over prose, no preamble, no recap of work just done, no re-explaining what the diff shows; applies to every response, not just status updates. Lead with the outcome; one-line statuses; no narration, filler, or diff-restating. Read what CI/linters/review bots already computed instead of re-deriving it. Mechanical rules belong in deterministic tests (changelog style, locale parity, version lockstep, CJK — all in `tests/`), never in agent effort. Targeted tests while iterating; full suites only before landing. `AGENTS.md` carries this contract for all agents — keep the two in sync.\n\n**Never accept a PR as-is (owner directive, 2026-07-20):** review findings — bot, agent, or human — get FIXED on the PR branch before merge (maintainer commits are fine and credit the contributor in the changelog); do not merge with known issues, do not merge-then-fix, do not leave findings as comments for someone else. Also merge current `main` into stale community branches before judging their CI, so the PR runs today's workflow gates (PR-green under an old workflow ≠ main-green).\n<!-- GSD:workflow-end -->\n\n\n\n<!-- GSD:profile-start -->\n## Developer Profile\n\n> Profile not yet configured. Run `/gsd-profile-user` to generate your developer profile.\n> This section is managed by `generate-claude-profile` -- do not edit manually.\n<!-- GSD:profile-end -->\n\n## Agent skills\n\n### Issue tracker\n\nGitHub Issues on `debpalash/VoiceStudio`, via the `gh` CLI. See `docs/agents/issue-tracker.md`.\n\n### Triage labels\n\nThe five canonical roles, each label string equal to its name. See `docs/agents/triage-labels.md`.\n\n### Domain docs\n\nSingle-context: `docs/adr/` plus a root `CONTEXT.md` that is created lazily and does not exist yet — skip it when absent. See `docs/agents/domain.md`.\n","docs/mcp.json":"{\n  \"_comment\": \"MCP client config for VoiceStudio. See docs/mcp.md for both connection modes.\",\n  \"_streamable_http\": \"If your MCP client speaks Streamable HTTP, point it directly at the running app: http://localhost:3900/mcp/ — no separate process needed (the server is mounted on the backend). Send an X-OmniVoice-Client-Id header to bind this agent to a specific voice.\",\n  \"_output_mode\": \"To keep audio out of the agent's context, set OMNIVOICE_MCP_OUTPUT_MODE=files and OMNIVOICE_MCP_BASE_PATH=<a directory visible to both backend and agent> on the BACKEND's environment for the mounted endpoint (or on a standalone `python -m backend.mcp_server` entry's env). The agent's working directory is valid only when it is mounted into the backend at the same path. See docs/mcp.md, 'Output mode and file inputs'.\",\n  \"mcpServers\": {\n    \"omnivoice\": {\n      \"command\": \"python\",\n      \"args\": [\"-m\", \"backend.mcp_shim\"],\n      \"cwd\": \"/path/to/VoiceStudio\",\n      \"env\": {\n        \"OMNIVOICE_PORT\": \"3900\",\n        \"OMNIVOICE_CLIENT_ID\": \"claude-code\"\n      }\n    }\n  }\n}\n","docs/agents/triage-labels.md":"# Triage Labels\n\nThe skills speak in terms of five canonical triage roles. This file maps those roles to the actual label strings used in this repo's issue tracker.\n\n| Label in mattpocock/skills | Label in our tracker | Meaning                                  |\n| -------------------------- | -------------------- | ---------------------------------------- |\n| `needs-triage`             | `needs-triage`       | Maintainer needs to evaluate this issue  |\n| `needs-info`               | `needs-info`         | Waiting on reporter for more information |\n| `ready-for-agent`          | `ready-for-agent`    | Fully specified, ready for an AFK agent  |\n| `ready-for-human`          | `ready-for-human`    | Requires human implementation            |\n| `wontfix`                  | `wontfix`            | Will not be actioned                     |\n\nWhen a skill mentions a role (e.g. \"apply the AFK-ready triage label\"), use the corresponding label string from this table.\n\nEdit the right-hand column to match whatever vocabulary you actually use.\n\n## Repo notes\n\n`wontfix` and `needs-info` **pre-date this file** — they were already in use on\n`debpalash/VoiceStudio` with exactly these names, which is why the mapping is an\nidentity mapping rather than an alias table. Reuse them; do not create variants\n(`won't-fix`, `needs-information`) alongside them.\n\n`needs-triage`, `ready-for-agent` and `ready-for-human` were created for this\nvocabulary on 2026-08-07.\n\nThis repo also carries labels outside the triage vocabulary — `bug`,\n`enhancement`, `documentation`, `question`, `duplicate`, `invalid`,\n`good first issue`, `help wanted`, `roadmap`, `from-discord`,\n`v0.3.0-investigate`, plus the area labels `install` (installer, setup and\nfirst-run problems) and `sponsor` (sponsorship inquiries). They classify *what*\nan issue is; the five above track *where it is in the queue*. The two sets are\northogonal — applying a triage label never means removing a type label.\n\nIssue templates apply only labels from this file: the bug and install-problem\nforms add `needs-triage` next to their type/area label; the feature and\nsponsor forms add only their type/area label. Do not reintroduce a bare\n`triage` label.\n","docs/agents/domain.md":"# Domain Docs\n\nHow the engineering skills should consume this repo's domain documentation when exploring the codebase.\n\n## Before exploring, read these\n\n- **`CONTEXT.md`** at the repo root — read it whenever it exists. It has not been created yet, so today this usually resolves to nothing; see below.\n- **`docs/adr/`** — read ADRs that touch the area you're about to work in.\n\nIf any of these files don't exist, **proceed silently**. Don't flag their absence; don't suggest creating them upfront. The `/domain-modeling` skill (reached via `/grill-with-docs` and `/improve-codebase-architecture`) creates them lazily when terms or decisions actually get resolved.\n\n`CLAUDE.md` is the de-facto context document today — it carries the project\nconstraints, the versioning/docs-sync/changelog/fix-quality rules, and the\nlocal-first guarantee. Read it as context alongside anything here.\n\n## File structure\n\nSingle-context repo (most repos):\n\n```text\n/\n├── CONTEXT.md\n├── docs/adr/\n│   ├── 0001-event-sourced-orders.md\n│   └── 0002-postgres-for-write-model.md\n└── src/\n```\n\nMulti-context repo (presence of `CONTEXT-MAP.md` at the root):\n\n```text\n/\n├── CONTEXT-MAP.md\n├── docs/adr/                          ← system-wide decisions\n└── src/\n    ├── ordering/\n    │   ├── CONTEXT.md\n    │   └── docs/adr/                  ← context-specific decisions\n    └── billing/\n        ├── CONTEXT.md\n        └── docs/adr/\n```\n\n## Use the glossary's vocabulary\n\nWhen your output names a domain concept (in an issue title, a refactor proposal, a hypothesis, a test name), use the term as defined in `CONTEXT.md`. Don't drift to synonyms the glossary explicitly avoids.\n\nIf the concept you need isn't in the glossary yet, that's a signal — either you're inventing language the project doesn't use (reconsider) or there's a real gap (note it for `/domain-modeling`).\n\n## Flag ADR conflicts\n\nIf your output contradicts an existing ADR, surface it explicitly rather than silently overriding:\n\n> _Contradicts ADR-0007 (event-sourced orders) — but worth reopening because…_\n",".claude/agents/owner-judge.md":"---\nname: owner-judge\ndescription: Reviews proposed changes to VoiceStudio against the owner's documented standards. Use before merging any PR, before tagging a release, and whenever another agent reports work as finished. Returns a verdict with blocking findings — it judges work, it does not authorise publishing.\nmodel: opus\ntools: Bash, Read, Grep, Glob, WebFetch\n---\n\n# The owner's standing review\n\nYou review changes to **VoiceStudio** the way its owner would. You are a\n**critic**, not an approver.\n\n## What you are, precisely\n\nYou carry the owner's documented standards and apply them without flinching.\nYou are not the owner, and you cannot consent on their behalf. Two things\nfollow, and they matter:\n\n- **You never authorise an irreversible or outward-facing action.** Publishing a\n  release, posting to users, deleting data, pushing to `main` — you can say\n  \"this meets the bar\" but you cannot say \"go ahead\". A judgement that a change\n  is *sound* is not permission to *ship* it. If asked to approve one of those,\n  say so plainly and give your technical verdict instead.\n- **Your job is to find what's wrong.** A review that returns \"looks good\" has\n  usually not been done. Assume the author — human or agent — has a blind spot,\n  and go looking for it. Reviews that agreed with the author have already cost\n  this project real bugs: a fix for the Linux blank window shipped that was\n  **completely inert**, and a dub-pipeline fix left a resurrection race, both\n  caught only because a reviewer attacked them instead of agreeing.\n\nBe fair, not hostile. A finding you cannot substantiate is noise, and noise\ntrains people to ignore you. Every finding needs a concrete failure: specific\ninput or state, and the wrong result it produces.\n\n## The standards (from CLAUDE.md — these are load-bearing)\n\n**Core value: a first-run that actually works.** A user who downloads the\ninstaller should reach a working output without hitting a wall, and when\nsomething breaks, the error or docs should say exactly what to do. Weigh\nfindings against this. An unactionable error message reaching a user is a real\ndefect here, not a nitpick.\n\n**Fix quality.** Root-cause fully; fix the whole *class*, not the reported\ninstance; add a regression test that genuinely fails before and passes after;\nharden against recurrence. Ask of every fix:\n- Does it address the cause, or the symptom?\n- Are there other instances of this same bug in the codebase, unfixed?\n- Would the test actually fail without the fix? Source-text assertions\n  (`assert \"foo(\" in inspect.getsource(...)`) usually would not — they pass\n  when the call is unreachable or its result discarded. This project has been\n  bitten by exactly that.\n- Is the test tautological? An assertion that holds for reasons unrelated to\n  the fix proves nothing.\n\n**Cross-platform parity (strict).** A feature shipping in default mode must\nbehave identically on macOS, Windows, and Linux. Platform-specific\n*implementation* is fine; divergent user-visible *default behaviour* is a P0 —\nfix it on the missing platform or move it behind explicit opt-in. There is no\nthird option. Check: does this change assume a POSIX path, a shell, a\ncase-sensitive filesystem, an evergreen browser engine, or a GPU that some\nsupported platform lacks?\n\n**Compatibility.** Existing engines must not need reinstalling. Existing\n`omnivoice_data/` must keep working with no manual migration; schema changes go\nthrough alembic with a tested upgrade path.\n\n**Local-first.** Nothing leaves the machine without an explicit yes, and the app\nstays fully functional with everything declined. No third-party endpoints for\nbug reporting or crash dumps. No PAT/token-based GitHub posting from the app.\nThe single sanctioned external endpoint is the opt-in, consent-gated PostHog EU\nanalytics, which must never grow exception or DOM autocapture.\n\n**Keep main green.** A merge must never break CI. Dependency, lockfile, and\nconfig changes must be validated against *every* consumer — `frontend/` is a bun\nworkspace monorepo whose lockfile is the repo-root `bun.lock`, and\n`deploy/Dockerfile` runs `bun install --frozen-lockfile`, so a `package.json`\nchange without a regenerated root lockfile is CI-green and Docker-red.\n\n**Versioning.** `frontend/package.json` is the single source of truth. Three\nmirrors stay in lockstep: `frontend/src-tauri/Cargo.toml`, `pyproject.toml`, and\n`_FALLBACK_VERSION` in `backend/core/version.py`. Never hand-edit a mirror or\nre-hardcode a literal in `tauri.conf.json`. `Cargo.lock` must match the manifest\nor `cargo build --locked` fails.\n\n**Docs-sync.** A change that alters what README, `.github/*`, or `docs/**`\ndescribe must update those docs in the *same* change. Stale docs are bugs.\n\n**Changelog.** Quiet and scannable: a short `**Highlights**` list in plain\nwords, then `### Changed` / `### Added` / `### Docs` / `### Fixed` / `### CI`\nsubsections where each entry is a one-liner ending in its `(#NNN)` ref with\ncontributor credit where due. Highlights bullets do **not** carry refs — the\n`###` entries do. Never edit an already-published version's section.\n\n**Localisation.** No hardcoded non-English user-facing text outside\n`frontend/src/i18n/`. Functional CJK is allowed via the allowlist in\n`tests/test_no_hardcoded_cjk.py`, with a justification.\n\n**Mechanical rules belong in tests, not in review.** Changelog style, locale\nparity, version lockstep and CJK are already enforced by pytest. Do not spend\nfindings on them — spend findings on what a test cannot judge: architecture,\ncross-file semantics, product intent, and whether the fix is actually a fix.\n\n## How to review\n\n1. **Read the actual change.** `git diff origin/main...HEAD`, or the PR diff.\n   Never review from a description alone — the description is the author's\n   belief about the change, which is precisely what may be wrong.\n2. **Reproduce the reasoning.** For a bug fix, find the original defect in the\n   code and confirm the change actually removes it. For the Linux fix mentioned\n   above, the give-away was that nothing in the diff could alter the search\n   order it claimed to alter.\n3. **Run what you can.** Targeted tests, the linter, a syntax check. Verify the\n   regression test fails without the fix — revert the source hunk, run the test,\n   restore it. A test that passes both ways is not a regression test.\n4. **Hunt the rest of the class.** Grep for the same idiom elsewhere. If the fix\n   is real and the pattern repeats, those are unfixed instances of a known bug.\n5. **Check the platforms the author could not.** Most work here is done on\n   macOS. Windows path handling, Linux packaging, and older WebView engines are\n   where unverified assumptions accumulate.\n\n## What to return\n\nA verdict — `BLOCK`, `CONCERNS`, or `PASS` — then the findings, most severe\nfirst. For each: the file and line, what breaks, and the concrete input or state\nthat breaks it. If you could not verify something important, say which and why,\nrather than implying coverage you do not have.\n\n`PASS` means \"I attacked this and it held\", not \"I read it and nothing jumped\nout\". If you did not try to break it, do not return `PASS`.\n\nState clearly when the remaining decision is the owner's — anything that\npublishes to users, or any change you could not verify on the platform it\naffects. Naming that boundary *is* part of the review.\n","docs/agents/issue-tracker.md":"# Issue tracker: GitHub\n\nIssues and PRDs for this repo live as GitHub issues on\n[`debpalash/VoiceStudio`](https://github.com/debpalash/VoiceStudio). Use the `gh`\nCLI for all operations.\n\n## Conventions\n\n- **Create an issue**: `gh issue create --title \"...\" --body \"...\"`. Use a heredoc for multi-line bodies.\n- **Read an issue**: `gh issue view <number> --comments`, filtering comments by `jq` and also fetching labels.\n- **List issues**: `gh issue list --state open --json number,title,body,labels,comments --jq '[.[] | {number, title, body, labels: [.labels[].name], comments: [.comments[].body]}]'` with appropriate `--label` and `--state` filters.\n- **Comment on an issue**: `gh issue comment <number> --body \"...\"`\n- **Apply / remove labels**: `gh issue edit <number> --add-label \"...\"` / `--remove-label \"...\"`\n- **Close**: `gh issue close <number> --comment \"...\"`\n\nInfer the repo from `git remote -v` — `gh` does this automatically when run inside a clone.\n\n## Pull requests as a triage surface\n\n**PRs as a request surface: no.** _(Set to `yes` if this repo treats external PRs as feature requests; `/triage` reads this flag.)_\n\nWhen set to `yes`, PRs run through the same labels and states as issues, using the `gh pr` equivalents:\n\n- **Read a PR**: `gh pr view <number> --comments` and `gh pr diff <number>` for the diff.\n- **List external PRs for triage**: `gh pr list --state open --json number,title,body,labels,author,authorAssociation,comments` then keep only `authorAssociation` of `CONTRIBUTOR`, `FIRST_TIME_CONTRIBUTOR`, or `NONE` (drop `OWNER`/`MEMBER`/`COLLABORATOR`).\n- **Comment / label / close**: `gh pr comment`, `gh pr edit --add-label`/`--remove-label`, `gh pr close`.\n\nGitHub shares one number space across issues and PRs, so a bare `#42` may be either — resolve with `gh pr view 42` and fall back to `gh issue view 42`.\n\n## Repo rules that override the generic flow\n\nThese come from `CLAUDE.md` and apply to anything a skill opens or merges here:\n\n- **Harvest bot reviews before merging.** CodeRabbit and Greptile auto-review every\n  PR. Read their inline comments — `gh api repos/debpalash/VoiceStudio/pulls/<n>/comments`\n  filtered by bot login — and triage them before merge. Never merge with an unread\n  Critical/P1. This applies to PRs a skill opened, not just human ones.\n- **Never merge with known findings outstanding.** Fix them on the PR branch; don't\n  merge-then-fix and don't leave them as comments for someone else.\n- **Gate every merge** on the \"Tests (backend + frontend)\" check passing and the PR\n  being `MERGEABLE`.\n- **Always pass an explicit `--body` to `gh pr merge --squash`.** Letting it\n  auto-generate copies every commit message, including any agent\n  `Co-authored-by:` or \"Generated with\" lines, which this repo forbids (see\n  the attribution rule in `CLAUDE.md`).\n- **Check the open-PR queue** before implementing any community-reported fix — a\n  contributor may already have submitted one.\n\n## When a skill says \"publish to the issue tracker\"\n\nCreate a GitHub issue.\n\n## When a skill says \"fetch the relevant ticket\"\n\nRun `gh issue view <number> --comments`.\n\n## Wayfinding operations\n\nUsed by `/wayfinder`. The **map** is a single issue with **child** issues as tickets.\n\n- **Map**: a single issue labelled `wayfinder:map`, holding the Notes / Decisions-so-far / Fog body. `gh issue create --label wayfinder:map`.\n- **Child ticket**: an issue linked to the map as a GitHub sub-issue (`gh api` on the sub-issues endpoint). Where sub-issues aren't enabled, add the child to a task list in the map body and put `Part of #<map>` at the top of the child body. Labels: `wayfinder:<type>` (`research`/`prototype`/`grilling`/`task`). Once claimed, the ticket is assigned to the driving dev.\n- **Blocking**: GitHub's **native issue dependencies** — the canonical, UI-visible representation. Add an edge with `gh api --method POST repos/<owner>/<repo>/issues/<child>/dependencies/blocked_by -F issue_id=<blocker-db-id>`, where `<blocker-db-id>` is the blocker's numeric **database id** (`gh api repos/<owner>/<repo>/issues/<n> --jq .id`, _not_ the `#number` or `node_id`). GitHub reports `issue_dependencies_summary.blocked_by` (open blockers only — the live gate). Where dependencies aren't available, fall back to a `Blocked by: #<n>, #<n>` line at the top of the child body. A ticket is unblocked when every blocker is closed.\n- **Frontier query**: list the map's open children (`gh issue list --state open`, scoped to the map's sub-issues / task list), drop any with an open blocker (`issue_dependencies_summary.blocked_by > 0`, or an open issue in the `Blocked by` line) or an assignee; first in map order wins.\n- **Claim**: `gh issue edit <n> --add-assignee @me` — the session's first write.\n- **Resolve**: `gh issue comment <n> --body \"<answer>\"`, then `gh issue close <n>`, then append a context pointer (gist + link) to the map's Decisions-so-far.\n","AGENTS.md":"## Active desktop: Electron only\n\nElectron (`electron/`) is the only desktop and web UI. The Tauri shell and legacy\nUI entrypoints are removed; do not restore build, runtime, release, or CI paths for\nthem. Triage reports from final Tauri installations toward the migration guide and\npreserve their immutable updater feeds. Some modules under `electron/src/shared/` remain\ntemporarily shared by Electron; they are not a runnable app. New UI, IPC, setup\ninstructions, tests, and browser assets belong in Electron; validate Electron on\nmacOS, Windows and Linux.\n\n## Mobile: native iOS and Android (owner-set 2026-10-17)\n\n`mobile/ios/` (Swift/SwiftUI) and `mobile/android/` (Kotlin/Compose) are native\napps that run models **on the phone** (TTS, dictation, voice cloning, dub\ntranslation; owner-set 2026-10-18) and can also drive a user's own VoiceStudio\ncomputer. Phone first: once models are downloaded they work offline with no\ncomputer; pairing adds the heavy engines, chosen per task. The companion-only\nbuild is the base, not the product. They implement one shared contract,\n`mobile/contract/SPEC.md`: a mobile feature ships on both or neither.\nTheme, API and strings are generated, never hand-copied: `bun\nscripts/export-mobile-tokens.ts` (from the Electron theme), `uv run python\nscripts/export_openapi.py` (from the backend) and the Electron locale catalogs;\n`tests/test_mobile_contract.py` fails on drift. Desktop/web UI still belongs in\nElectron only.\n\n# Agent Rules — VoiceStudio\n\nBinding for every AI agent (Claude, Codex, Cursor, review bots, …). CLAUDE.md is the full constitution; this is the operating contract. When they conflict, CLAUDE.md wins.\n\n## Token economy (owner directive, 2026-07-20; tightened 2026-07-28)\n- **Default to the shortest response that fully answers.** Outlines and tables over prose; no preamble, no recap of what you just did, no re-explaining a fix the diff already shows. Applies to every response, not just status updates.\n- Lead with the outcome. No narration, no restating diffs, no filler praise, no plans you're about to execute anyway.\n- Status updates: one line. Final reports: only what changes the reader's next action.\n- Don't re-derive what CI, linters, or review bots already computed — read their output first (`gh pr checks`, bot comments via `gh api .../pulls/N/comments`).\n- Mechanical rules live in deterministic tests, never in agent effort: changelog style (`tests/test_changelog_style.py`), locale parity (`tests/test_locale_parity.py`), version lockstep (`tests/test_app_version.py`), CJK (`tests/test_no_hardcoded_cjk.py`).\n- Run targeted tests while iterating; full suites only before landing.\n- Tests and CI simulate CI honestly: `HF_HUB_OFFLINE=1` + empty `HF_HUB_CACHE` — a populated dev cache masks real failures.\n\n## Cross-platform parity: behaviour, not performance\n- The parity rule covers user-visible BEHAVIOUR. Hardware acceleration varies by host by design (CUDA/MPS/DirectML, Triton availability, `torch.compile`); skipping an optimization where it physically cannot work is not a parity violation.\n- Do not \"fix\" a parity finding by disabling a working optimization everywhere. That trades a real regression for a semantic one.\n- A feature the user can see and use on one OS but not another IS a violation. Judge by what the user can do, not by how fast it runs.\n\n## Merge protocol (hard rules)\n1. Never merge without review. Harvest CodeRabbit + Greptile comments first; never merge with an unread Critical/P1.\n2. Never accept a PR as-is: fix findings ON the PR branch pre-merge (maintainer commits fine; credit contributors in CHANGELOG). No merge-then-fix, no comment-and-walk-away.\n3. Merge current `main` into stale branches before judging their CI — PR-green under an old workflow ≠ main-green.\n4. Gate: \"Tests (backend + frontend)\" green + MERGEABLE.\n5. After EVERY merge: watch `main`'s own post-merge runs to green (`gh run list --branch main`). Red main = drop everything and fix.\n\n## Change rules (see CLAUDE.md for full text)\n- Root-cause the class, not the instance; fail-before/pass-after regression test; smallest correct change.\n- Default behavior identical on macOS/Windows/Linux; platform-only features go behind explicit opt-in. Divergent default = P0.\n- Local-first: no new required network calls; any HF download gated on installed-ness or explicit user action; all synthetic audio through the `mark_synthetic` chokepoint. Sanctioned calls are listed in `.github/CONTRIBUTING.md` → Quality gates: user-started first-run setup (ffmpeg from GitHub `zackees/ffmpeg_bins`, the huggingface.co/hf-mirror.com reachability probe, HF model downloads), opening/enabling the galleries (jsDelivr manifest, GitHub Releases), packaged update checks, user-clicked yt-dlp updates from PyPI, consent-gated analytics, prefilled-URL bug reports, the Pro licence check after a key is entered, and VoiceStudio Cloud sign-in/account calls (and settings sync once cloud sync is on) only after the user turns them on (off by default; switching off stops them at once). Owner-approved exception (2026-09-28): the public GitHub star count may refresh automatically every 20 minutes, without credentials/referrer or user content; offline use remains unaffected.\n- Every user-facing string via i18n, present in ALL 21 `electron/src/renderer/src/i18n/locales/*.json` files (the catalog the app loads) with real translations; `tests/test_locale_parity.py` and Electron `locale:check` enforce it. The legacy `electron/src/shared/i18n/` catalog is loaded only by shared-module tests.\n- Docs-sync in the same PR. CHANGELOG Unreleased: quiet one-liners ending `(#N)` + `— thanks @user!` for community work, under a short `**Highlights**` list.\n- Tagged release announcements lead with the biggest user-visible change; redesigns need real UI screenshots and migrations need installer links and steps. Verify all contributor credits from the tag comparison and included PRs; list authors and bug reporters separately (see `docs/RELEASING.md`).\n- Versioning: root `package.json` is the single source of truth; never bump without the owner asking.\n- JavaScript dependency changes require regenerating root `bun.lock` (Docker runs `--frozen-lockfile`).\n- Attribution: commits, PR descriptions and comments carry only the submitter's git identity. Never credit an agent (no agent `Co-authored-by:`, \"Generated with …\", session links) and never add other names/emails. Human co-authors are fine. Enforced by the `commit-identity` check.\n- Issues: absorb or decline — never defer to a future version. Check the open-PR queue before implementing community-reported fixes.\n\n## Shared select controls\n\n- Use `electron/src/shared/components/SearchableSelect.jsx` for all new or redesigned select boxes. Reuse `VoiceSelector` for voice choices. Do not introduce native `<select>` controls.\n- Provide a localized `ariaLabel`; use `menuPortal` inside scrolling or clipping containers. Preserve keyboard selection and disabled states.\n\n## Agent skills\n\nProject development skills are pinned in `skills-lock.json` and installed under\n`.agents/skills/`: Vite and FastAPI.\nRepository rules and tracker mappings override generic skill guidance.\n\n### Issue tracker\n\nGitHub Issues on `debpalash/VoiceStudio`, via the `gh` CLI. See `docs/agents/issue-tracker.md`.\n\n### Triage labels\n\nThe five canonical roles, each label string equal to its name. See `docs/agents/triage-labels.md`.\n\n### Domain docs\n\nSingle-context: `docs/adr/` plus a root `CONTEXT.md` that is created lazily and does not exist yet — skip it when absent. See `docs/agents/domain.md`.\n",".claude/skills/omnivoice/LEGACY.md":"# VoiceStudio compatibility entry\n\nThe current cross-agent package is [voicestudio](../../../../skills/voicestudio/SKILL.md).\nFor new installations use `npx skills add debpalash/VoiceStudio --skill voicestudio`.\n\nUse the running backend at the user's configured address (default\n`http://localhost:3900`). Check `/health`, discover `/openapi.json` and\n`/v1/audio/voices`, then use the installed schema for speech, transcription,\nprofiles, and jobs. The HTTP MCP endpoint is `/mcp`; discover tools from the\nconnected server instead of assuming this older package's tool inventory.\n\nLaunch the installed Electron app if the backend is unavailable. For source\ndevelopment follow the checkout's Electron README. Existing helpers in\n`scripts/` support legacy source installations; inspect their environment\nand dependency assumptions before running them.\n\nModel downloads and remote services require the user's choice. Never silently\ninstall models, promise fixed latency, or treat compatibility voice names as\nreal provider voices. Validate saved audio and asynchronous job completion\nbefore reporting success. Protected backends require configured credentials;\nnever disable authentication to make an example work.\n\nSource and current setup documentation:\nhttps://github.com/debpalash/VoiceStudio\n\nThis archived entry is not an installable skill. Existing installations should\nremove the old `omnivoice` / `oss-maintainer` entries and install `voicestudio` /\n`voicestudio-maintainer` from the canonical repository. Legacy helpers remain\nfor existing users; the Electron supervisor is the preferred launcher.\n","tests/evals/suites/dub_translation_naturalness.yaml":"# Suites Skill\n\nPath: `tests/evals/suites/dub_translation_naturalness.yaml`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/tests/evals/suites/dub_translation_naturalness.yaml)",".claude/skills/omnivoice/references/engines-comparison.md":"# References Skill\n\nPath: `.claude/skills/omnivoice/references/engines-comparison.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/references/engines-comparison.md)",".claude/skills/omnivoice/references/mcp-setup.md":"# References Skill\n\nPath: `.claude/skills/omnivoice/references/mcp-setup.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/references/mcp-setup.md)",".claude/skills/omnivoice/scripts/check-health.sh":"# Claude Directive: check-health.sh\n\nPath: `.claude/skills/omnivoice/scripts/check-health.sh`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/scripts/check-health.sh)",".claude/skills/omnivoice/scripts/record-reference.sh":"# Claude Directive: record-reference.sh\n\nPath: `.claude/skills/omnivoice/scripts/record-reference.sh`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/scripts/record-reference.sh)",".claude/skills/omnivoice/scripts/start-backend.sh":"# Claude Directive: start-backend.sh\n\nPath: `.claude/skills/omnivoice/scripts/start-backend.sh`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/scripts/start-backend.sh)",".claude/skills/omnivoice/scripts/stop-backend.sh":"# Claude Directive: stop-backend.sh\n\nPath: `.claude/skills/omnivoice/scripts/stop-backend.sh`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/scripts/stop-backend.sh)"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"## Active desktop: Electron only\n\nElectron (`electron/`) is the only desktop and web UI. The Tauri shell and legacy\nUI entrypoints are removed; do not restore build, runtime, release, or CI paths for\nthem. Triage reports from final Tauri installations toward the migration guide and\npreserve their immutable updater feeds. Some modules under `electron/src/shared/` remain\ntemporarily shared by Electron; they are not a runnable app. New UI, IPC, setup\ninstructions, tests, and browser assets belong in Electron; validate Electron on\nmacOS, Windows and Linux.\n\n## Mobile: native iOS and Android (owner-set 2026-10-17)\n\n`mobile/ios/` (Swift/SwiftUI) and `mobile/android/` (Kotlin/Compose) are native\napps that run models **on the phone** (TTS, dictation, voice cloning, dub\ntranslation; owner-set 2026-10-18) and can also drive a user's own VoiceStudio\ncomputer. Phone first: once models are downloaded they work offline with no\ncomputer; pairing adds the heavy engines, chosen per task. The companion-only\nbuild is the base, not the product. They implement one shared contract,\n`mobile/contract/SPEC.md`: a mobile feature ships on both or neither.\nTheme, API and strings are generated, never hand-copied: `bun\nscripts/export-mobile-tokens.ts` (from the Electron theme), `uv run python\nscripts/export_openapi.py` (from the backend) and the Electron locale catalogs;\n`tests/test_mobile_contract.py` fails on drift. Desktop/web UI still belongs in\nElectron only.\n\n# Agent Rules — VoiceStudio\n\nBinding for every AI agent (Claude, Codex, Cursor, review bots, …). CLAUDE.md is the full constitution; this is the operating contract. When they conflict, CLAUDE.md wins.\n\n## Token economy (owner directive, 2026-07-20; tightened 2026-07-28)\n- **Default to the shortest response that fully answers.** Outlines and tables over prose; no preamble, no recap of what you just did, no re-explaining a fix the diff already shows. Applies to every response, not just status updates.\n- Lead with the outcome. No narration, no restating diffs, no filler praise, no plans you're about to execute anyway.\n- Status updates: one line. Final reports: only what changes the reader's next action.\n- Don't re-derive what CI, linters, or review bots already computed — read their output first (`gh pr checks`, bot comments via `gh api .../pulls/N/comments`).\n- Mechanical rules live in deterministic tests, never in agent effort: changelog style (`tests/test_changelog_style.py`), locale parity (`tests/test_locale_parity.py`), version lockstep (`tests/test_app_version.py`), CJK (`tests/test_no_hardcoded_cjk.py`).\n- Run targeted tests while iterating; full suites only before landing.\n- Tests and CI simulate CI honestly: `HF_HUB_OFFLINE=1` + empty `HF_HUB_CACHE` — a populated dev cache masks real failures.\n\n## Cross-platform parity: behaviour, not performance\n- The parity rule covers user-visible BEHAVIOUR. Hardware acceleration varies by host by design (CUDA/MPS/DirectML, Triton availability, `torch.compile`); skipping an optimization where it physically cannot work is not a parity violation.\n- Do not \"fix\" a parity finding by disabling a working optimization everywhere. That trades a real regression for a semantic one.\n- A feature the user can see and use on one OS but not another IS a violation. Judge by what the user can do, not by how fast it runs.\n\n## Merge protocol (hard rules)\n1. Never merge without review. Harvest CodeRabbit + Greptile comments first; never merge with an unread Critical/P1.\n2. Never accept a PR as-is: fix findings ON the PR branch pre-merge (maintainer commits fine; credit contributors in CHANGELOG). No merge-then-fix, no comment-and-walk-away.\n3. Merge current `main` into stale branches before judging their CI — PR-green under an old workflow ≠ main-green.\n4. Gate: \"Tests (backend + frontend)\" green + MERGEABLE.\n5. After EVERY merge: watch `main`'s own post-merge runs to green (`gh run list --branch main`). Red main = drop everything and fix.\n\n## Change rules (see CLAUDE.md for full text)\n- Root-cause the class, not the instance; fail-before/pass-after regression test; smallest correct change.\n- Default behavior identical on macOS/Windows/Linux; platform-only features go behind explicit opt-in. Divergent default = P0.\n- Local-first: no new required network calls; any HF download gated on installed-ness or explicit user action; all synthetic audio through the `mark_synthetic` chokepoint. Sanctioned calls are listed in `.github/CONTRIBUTING.md` → Quality gates: user-started first-run setup (ffmpeg from GitHub `zackees/ffmpeg_bins`, the huggingface.co/hf-mirror.com reachability probe, HF model downloads), opening/enabling the galleries (jsDelivr manifest, GitHub Releases), packaged update checks, user-clicked yt-dlp updates from PyPI, consent-gated analytics, prefilled-URL bug reports, the Pro licence check after a key is entered, and VoiceStudio Cloud sign-in/account calls (and settings sync once cloud sync is on) only after the user turns them on (off by default; switching off stops them at once). Owner-approved exception (2026-09-28): the public GitHub star count may refresh automatically every 20 minutes, without credentials/referrer or user content; offline use remains unaffected.\n- Every user-facing string via i18n, present in ALL 21 `electron/src/renderer/src/i18n/locales/*.json` files (the catalog the app loads) with real translations; `tests/test_locale_parity.py` and Electron `locale:check` enforce it. The legacy `electron/src/shared/i18n/` catalog is loaded only by shared-module tests.\n- Docs-sync in the same PR. CHANGELOG Unreleased: quiet one-liners ending `(#N)` + `— thanks @user!` for community work, under a short `**Highlights**` list.\n- Tagged release announcements lead with the biggest user-visible change; redesigns need real UI screenshots and migrations need installer links and steps. Verify all contributor credits from the tag comparison and included PRs; list authors and bug reporters separately (see `docs/RELEASING.md`).\n- Versioning: root `package.json` is the single source of truth; never bump without the owner asking.\n- JavaScript dependency changes require regenerating root `bun.lock` (Docker runs `--frozen-lockfile`).\n- Attribution: commits, PR descriptions and comments carry only the submitter's git identity. Never credit an agent (no agent `Co-authored-by:`, \"Generated with …\", session links) and never add other names/emails. Human co-authors are fine. Enforced by the `commit-identity` check.\n- Issues: absorb or decline — never defer to a future version. Check the open-PR queue before implementing community-reported fixes.\n\n## Shared select controls\n\n- Use `electron/src/shared/components/SearchableSelect.jsx` for all new or redesigned select boxes. Reuse `VoiceSelector` for voice choices. Do not introduce native `<select>` controls.\n- Provide a localized `ariaLabel`; use `menuPortal` inside scrolling or clipping containers. Preserve keyboard selection and disabled states.\n\n## Agent skills\n\nProject development skills are pinned in `skills-lock.json` and installed under\n`.agents/skills/`: Vite and FastAPI.\nRepository rules and tracker mappings override generic skill guidance.\n\n### Issue tracker\n\nGitHub Issues on `debpalash/VoiceStudio`, via the `gh` CLI. See `docs/agents/issue-tracker.md`.\n\n### Triage labels\n\nThe five canonical roles, each label string equal to its name. See `docs/agents/triage-labels.md`.\n\n### Domain docs\n\nSingle-context: `docs/adr/` plus a root `CONTEXT.md` that is created lazily and does not exist yet — skip it when absent. See `docs/agents/domain.md`.\n","isInternal":false,"tokens":1764,"sizeBytes":7615},{"name":"SKILL.md","path":".agents/skills/fastapi-python/SKILL.md","rawUrl":"https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.agents/skills/fastapi-python/SKILL.md","title":"fastapi-python","category":"anthropic-skill","format":"markdown","content":"---\nname: fastapi-python\ndescription: Expert in FastAPI Python development with best practices for APIs and async operations\n---\n\n# FastAPI Python\n\nYou are an expert in FastAPI and Python backend development.\n\n## Key Principles\n\n- Write concise, technical responses with accurate Python examples\n- Favor functional, declarative programming over class-based approaches\n- Prioritize modularization to eliminate code duplication\n- Use descriptive variable names with auxiliary verbs (e.g., `is_active`, `has_permission`)\n- Employ lowercase with underscores for file/directory naming (e.g., `routers/user_routes.py`)\n- Export routes and utilities explicitly\n- Follow the RORO (Receive an Object, Return an Object) pattern\n\n## Python/FastAPI Standards\n\n- Use `def` for pure functions, `async def` for asynchronous operations\n- Use type hints for all function signatures. Prefer Pydantic models over raw dictionaries\n- Structure: exported router, sub-routes, utilities, static content, types (models, schemas)\n- Use ordinary Python control flow; prefer readability over compressed one-line conditionals\n\n## Error Handling\n\n- Handle edge cases at function entry points\n- Employ early returns for error conditions\n- Place happy path logic last\n- Avoid unnecessary else statements; use if-return patterns\n- Implement guard clauses for preconditions\n- Provide proper error logging and user-friendly messaging\n\n## FastAPI-Specific Guidelines\n\n- Use functional components (plain functions) and Pydantic models for input validation\n- Declare routes with clear return type annotations\n- Prefer lifespan context managers for managing startup and shutdown events\n- Leverage middleware for logging, error monitoring, and optimization\n- Use HTTPException for expected errors and model them as specific HTTP responses\n- Apply Pydantic's BaseModel consistently for validation\n\n## Performance Optimization\n\n- Minimize blocking I/O. In `async def` handlers, use awaitable database/API clients; put synchronous SQLite or other blocking work in synchronous routes or explicitly offload it\n- Implement caching with Redis or in-memory stores\n- Optimize Pydantic serialization/deserialization\n- Use lazy loading for large datasets\n\n## Key Conventions\n\n1. Rely on FastAPI's dependency injection system\n2. Prioritize API performance metrics (response time, latency, throughput)\n3. Structure routes and dependencies for readability and maintainability\n\n## Dependencies\n\nFastAPI, Pydantic v2, asyncpg/aiomysql, SQLAlchemy 2.0\n","frontmatter":{"name":"fastapi-python","description":"Expert in FastAPI Python development with best practices for APIs and async operations"},"isInternal":false,"tokens":503,"sizeBytes":2495},{"name":"SKILL.md","path":".agents/skills/vite/SKILL.md","rawUrl":"https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.agents/skills/vite/SKILL.md","title":"vite","category":"anthropic-skill","format":"markdown","content":"---\nname: vite\ndescription: Expert guidance for Vite development with modern build tooling, HMR, framework integrations, and performance optimization\n---\n\n# Vite Development\n\nYou are an expert in Vite, modern JavaScript/TypeScript build tooling, and frontend development.\n\n## Key Principles\n\n- Leverage native ES modules for fast development\n- Use Vite's opinionated defaults when possible\n- Configure only what needs customization\n- Understand the dev/build differences\n- Optimize for both development speed and production performance\n\n## Project Setup\n\n### Basic Configuration\n```typescript\n// vite.config.ts\nimport { defineConfig } from 'vite';\nimport react from '@vitejs/plugin-react';\n\nexport default defineConfig({\n  plugins: [react()],\n  server: {\n    port: 3000,\n    open: true,\n  },\n  build: {\n    outDir: 'dist',\n    sourcemap: true,\n  },\n});\n```\n\n### Path Aliases\n```typescript\nimport { defineConfig } from 'vite';\n\nexport default defineConfig({\n  resolve: {\n    alias: {\n      '@': new URL('./src', import.meta.url).pathname,\n      '@components': new URL('./src/components', import.meta.url).pathname,\n      '@utils': new URL('./src/utils', import.meta.url).pathname,\n    },\n  },\n});\n```\n\n## Environment Variables\n\n### Usage\n```typescript\n// .env\nVITE_API_URL=https://api.example.com\nVITE_APP_TITLE=My App\n\n// In code\nconst apiUrl = import.meta.env.VITE_API_URL;\nconst isDev = import.meta.env.DEV;\nconst isProd = import.meta.env.PROD;\nconst mode = import.meta.env.MODE;\n```\n\n### Type Definitions\n```typescript\n// src/vite-env.d.ts\n/// <reference types=\"vite/client\" />\n\ninterface ImportMetaEnv {\n  readonly VITE_API_URL: string;\n  readonly VITE_APP_TITLE: string;\n}\n\ninterface ImportMeta {\n  readonly env: ImportMetaEnv;\n}\n```\n\n## Hot Module Replacement\n\n### Manual HMR\n```typescript\n// For libraries without HMR support\nif (import.meta.hot) {\n  import.meta.hot.accept('./module.ts', (newModule) => {\n    // Handle the updated module\n    console.log('Module updated:', newModule);\n  });\n\n  import.meta.hot.dispose(() => {\n    // Cleanup before module is replaced\n  });\n}\n```\n\n## Asset Handling\n\n### Static Assets\n```typescript\n// Import as URL\nimport imageUrl from './image.png';\n// <img src={imageUrl} />\n\n// Import as string (raw)\nimport shaderCode from './shader.glsl?raw';\n\n// Import as worker\nimport Worker from './worker.ts?worker';\nconst worker = new Worker();\n```\n\n### Public Directory\n```\npublic/\n├── favicon.ico      # Served at /favicon.ico\n├── robots.txt       # Served at /robots.txt\n└── images/          # Served at /images/\n```\n\n## Framework Integrations\n\n### React\n```typescript\nimport { defineConfig } from 'vite';\nimport react from '@vitejs/plugin-react';\n\nexport default defineConfig({\n  plugins: [\n    react({\n      // Babel plugins\n      babel: {\n        plugins: ['@emotion/babel-plugin'],\n      },\n    }),\n  ],\n});\n```\n\n### Vue\n```typescript\nimport { defineConfig } from 'vite';\nimport vue from '@vitejs/plugin-vue';\n\nexport default defineConfig({\n  plugins: [vue()],\n});\n```\n\n### Svelte\n```typescript\nimport { defineConfig } from 'vite';\nimport { svelte } from '@sveltejs/vite-plugin-svelte';\n\nexport default defineConfig({\n  plugins: [svelte()],\n});\n```\n\n## Build Optimization\n\n### Code Splitting\n```typescript\n// Dynamic imports create separate chunks\nconst AdminPanel = lazy(() => import('./AdminPanel'));\n\n// Manual chunks\nexport default defineConfig({\n  build: {\n    rollupOptions: {\n      output: {\n        manualChunks: {\n          vendor: ['react', 'react-dom'],\n          utils: ['lodash', 'date-fns'],\n        },\n      },\n    },\n  },\n});\n```\n\n### Chunk Size Optimization\n```typescript\nexport default defineConfig({\n  build: {\n    chunkSizeWarningLimit: 500,\n    rollupOptions: {\n      output: {\n        manualChunks(id) {\n          if (id.includes('node_modules')) {\n            return id.split('node_modules/')[1].split('/')[0];\n          }\n        },\n      },\n    },\n  },\n});\n```\n\n## CSS Handling\n\n### CSS Modules\n```typescript\n// styles.module.css is auto-detected\nimport styles from './styles.module.css';\n\n// <div className={styles.container}>\n```\n\n### PostCSS\n```javascript\n// postcss.config.js\nexport default {\n  plugins: {\n    tailwindcss: {},\n    autoprefixer: {},\n  },\n};\n```\n\n### Preprocessors\n```typescript\n// Automatically handled with package installed\n// npm install -D sass\nimport './styles.scss';\n```\n\n## Proxy Configuration\n\n```typescript\nexport default defineConfig({\n  server: {\n    proxy: {\n      '/api': {\n        target: 'http://localhost:4000',\n        changeOrigin: true,\n        rewrite: (path) => path.replace(/^\\/api/, ''),\n      },\n      '/socket.io': {\n        target: 'ws://localhost:4000',\n        ws: true,\n      },\n    },\n  },\n});\n```\n\n## Plugin Development\n\n```typescript\n// my-vite-plugin.ts\nimport type { Plugin } from 'vite';\n\nexport function myPlugin(): Plugin {\n  return {\n    name: 'my-plugin',\n\n    // Hook: modify config\n    config(config, { mode }) {\n      return {\n        define: {\n          __BUILD_TIME__: JSON.stringify(new Date().toISOString()),\n        },\n      };\n    },\n\n    // Hook: transform code\n    transform(code, id) {\n      if (id.endsWith('.md')) {\n        return {\n          code: `export default ${JSON.stringify(code)}`,\n          map: null,\n        };\n      }\n    },\n\n    // Hook: configure dev server\n    configureServer(server) {\n      server.middlewares.use((req, res, next) => {\n        // Custom middleware\n        next();\n      });\n    },\n  };\n}\n```\n\n## Testing with Vitest\n\n```typescript\n// vitest.config.ts\nimport { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  test: {\n    globals: true,\n    environment: 'jsdom',\n    setupFiles: './src/test/setup.ts',\n    coverage: {\n      provider: 'v8',\n      reporter: ['text', 'json', 'html'],\n    },\n  },\n});\n```\n\n## SSR Configuration\n\n```typescript\nexport default defineConfig({\n  build: {\n    ssr: true,\n    rollupOptions: {\n      input: './src/entry-server.ts',\n    },\n  },\n  ssr: {\n    external: ['express'],\n    noExternal: ['my-ui-library'],\n  },\n});\n```\n\n## Library Mode\n\n```typescript\nexport default defineConfig({\n  build: {\n    lib: {\n      entry: './src/index.ts',\n      name: 'MyLib',\n      fileName: (format) => `my-lib.${format}.js`,\n    },\n    rollupOptions: {\n      external: ['react', 'react-dom'],\n      output: {\n        globals: {\n          react: 'React',\n          'react-dom': 'ReactDOM',\n        },\n      },\n    },\n  },\n});\n```\n\n## Best Practices\n\n- Use `vite preview` to test production builds locally\n- Keep dependencies that support ESM in regular deps\n- Use `optimizeDeps.include` for CommonJS dependencies\n- Enable `build.sourcemap` for debugging production\n- Use `server.warmup` for faster dev server starts\n","frontmatter":{"name":"vite","description":"Expert guidance for Vite development with modern build tooling, HMR, framework integrations, and performance optimization"},"isInternal":false,"tokens":1646,"sizeBytes":6740},{"name":"LEGACY.md","path":".claude/skills/omnivoice/LEGACY.md","rawUrl":"https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/LEGACY.md","title":"Omnivoice Skill","category":"anthropic-skill","format":"markdown","content":"# VoiceStudio compatibility entry\n\nThe current cross-agent package is [voicestudio](../../../../skills/voicestudio/SKILL.md).\nFor new installations use `npx skills add debpalash/VoiceStudio --skill voicestudio`.\n\nUse the running backend at the user's configured address (default\n`http://localhost:3900`). Check `/health`, discover `/openapi.json` and\n`/v1/audio/voices`, then use the installed schema for speech, transcription,\nprofiles, and jobs. The HTTP MCP endpoint is `/mcp`; discover tools from the\nconnected server instead of assuming this older package's tool inventory.\n\nLaunch the installed Electron app if the backend is unavailable. For source\ndevelopment follow the checkout's Electron README. Existing helpers in\n`scripts/` support legacy source installations; inspect their environment\nand dependency assumptions before running them.\n\nModel downloads and remote services require the user's choice. Never silently\ninstall models, promise fixed latency, or treat compatibility voice names as\nreal provider voices. Validate saved audio and asynchronous job completion\nbefore reporting success. Protected backends require configured credentials;\nnever disable authentication to make an example work.\n\nSource and current setup documentation:\nhttps://github.com/debpalash/VoiceStudio\n\nThis archived entry is not an installable skill. Existing installations should\nremove the old `omnivoice` / `oss-maintainer` entries and install `voicestudio` /\n`voicestudio-maintainer` from the canonical repository. Legacy helpers remain\nfor existing users; the Electron supervisor is the preferred launcher.\n","isInternal":false,"tokens":328,"sizeBytes":1604},{"name":"engines-comparison.md","path":".claude/skills/omnivoice/references/engines-comparison.md","rawUrl":"https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/references/engines-comparison.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `.claude/skills/omnivoice/references/engines-comparison.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/references/engines-comparison.md)","tokens":300,"sizeBytes":240},{"name":"mcp-setup.md","path":".claude/skills/omnivoice/references/mcp-setup.md","rawUrl":"https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/references/mcp-setup.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `.claude/skills/omnivoice/references/mcp-setup.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/references/mcp-setup.md)","tokens":300,"sizeBytes":222},{"name":"SKILL.md","path":"skills/voicestudio-maintainer/SKILL.md","rawUrl":"https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/skills/voicestudio-maintainer/SKILL.md","title":"voicestudio-maintainer","category":"anthropic-skill","format":"markdown","content":"---\nname: voicestudio-maintainer\ndescription: Triage GitHub issues, review contributor pull requests, diagnose CI, and prepare explicitly requested releases for VoiceStudio's Electron desktop app and Python backend. Use for repository maintenance work, not ordinary VoiceStudio audio generation.\n---\n\n# VoiceStudio maintenance\n\nRead the target repository's AGENTS.md, CLAUDE.md, contribution guide, and release documentation first. Their policies override this general workflow. Installing this skill does not authorize merges, releases, issue closures, or messages to contributors.\n\n## Triage and implementation\n\n- Inspect current code and existing PRs before duplicating a reported fix. Reuse contributor work where it solves the problem; retain attribution.\n- Reproduce the reported behavior where possible. Separate confirmed failures from diagnosis, and record meaningful limitations in the PR.\n- Fix the cause with the smallest complete change. Test observable behavior where it can regress; do not mistake a source-text assertion for an end-to-end test.\n- Preserve local changes. Use an isolated worktree when branch switching would disturb them.\n- Read existing CI failures and reviewer comments before rerunning work. Diagnose failures before retries; never hide a failing gate behind a successful piped command.\n- Keep user-facing docs and required translations aligned with the implementation.\n\n## Review and authorized landing\n\nReview the current diff, bot findings, and required checks against current main. Resolve material findings on the PR branch before landing; do not merge first and promise a follow-up. Refresh stale branches using the repository's policy and preserve contributor commits.\n\nBefore an authorized merge, verify required checks are green, the head has not changed, and the PR is mergeable. After landing, inspect main's own runs; investigate regressions immediately. Report remaining blockers without inventing a successful verification.\n\n## Release preparation\n\nPreparing CI or packaging is distinct from publishing. Do not tag, bump versions, enable publishing, or cut a release unless that action is authorized.\n\nUse the repository's version source of truth, changelog format, supported platforms, and distribution channels. Validate packaging and workflows without publishing when that is the requested scope. After an authorized release, verify actual artifacts, release notes, updater metadata, and requested registry channels; a green build alone does not prove distribution.\n\n## Communication\n\nLead with the outcome and evidence. Credit concrete contributor work. Do not close stale issues merely because of age, or claim reporter confirmation that has not occurred. For authorized closures, give the resolution and what evidence would justify reopening.\n\n## VoiceStudio-specific routing\n\nWhen maintaining debpalash/VoiceStudio, consult its current rules rather than old architecture assumptions:\n- Electron development and packaging: `electron/README.md`, `electron/package.json`, and `.github/workflows/`.\n- Backend contracts: running `/openapi.json`, `backend/api/`, and targeted tests.\n- Release channels and version ownership: `docs/RELEASING.md` and CLAUDE.md. Never infer a version bump from a fix request.\n- Read CodeRabbit/Greptile findings and required CI before merging. Follow main's post-merge CI.\n- Preserve local-first behavior, cross-platform behavior, model-install consent, synthetic-audio marking, and localization requirements.\n\n## Current development commands\n\nRun from the repository root:\n\n```sh\nbun install\nbun run setup:api        # prepare the source Python runtime explicitly\nbun run dev              # Electron + supervised backend\nbun run typecheck        # Electron main, preload, and renderer\nbun run test             # Electron tests\nbun run check:electron   # types, tests, build, packaging contract\nbun run dist             # local installers; publishing disabled\n```\n\n`electron/src/main/` owns lifecycle, IPC, native helpers, and backend supervision;\n`electron/src/preload/` exposes the renderer bridge; `electron/src/renderer/src/`\ncontains the React app. Keep privileged filesystem/process work out of the renderer.\n`electron/src/shared/` holds modules shared with the browser build; it is not a\nrunnable app. `backend/` supplies the shared Python API; `native/desktop-bridge/`\nsupplies native capabilities. `frontend/` only receives the browser build output\n(`bun run build:web` → `frontend/dist/`, served by the backend in Docker). Do not\nrename internal `omnivoice` packages, environment keys, or data paths as a\nbranding cleanup.\n\nElectron is the only desktop app and web UI. The Tauri shell is removed; do not\nrestore it. Its final v0.5.3 updater feeds are immutable compatibility assets,\nand old Tauri installs move over with `docs/electron-migration.md`.\nUse `electron-build.yml` for artifact-only packaging rehearsals; inspect its\nresults for Windows x64, Linux, macOS Intel, and macOS Apple Silicon (Windows\nARM64 is an experimental leg that may fail without blocking).\nDo not dispatch release/publishing workflows to test packaging. Signing, updater\nmigration, and successful installation are separate checks from a green build.\nThe app version comes from the root `package.json` (mirrored in `pyproject.toml`\nand `backend/core/version.py`); do not bump it without an explicit versioning task.\n\nFor backend tests, use the repo's CI dependencies and an empty temporary\n`HF_HUB_CACHE` with `HF_HUB_OFFLINE=1`; installed developer models must not hide\nmissing fixtures. Run targeted tests while editing and the required full checks\nbefore landing. Existing CI failures remain blockers, not implied waivers.\n","frontmatter":{"name":"voicestudio-maintainer","description":"Triage GitHub issues, review contributor pull requests, diagnose CI, and prepare explicitly requested releases for VoiceStudio's Electron desktop app and Python backend. Use for repository maintenance work, not ordinary VoiceStudio audio generation."},"isInternal":false,"tokens":1144,"sizeBytes":5696},{"name":"SKILL.md","path":"skills/voicestudio/SKILL.md","rawUrl":"https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/skills/voicestudio/SKILL.md","title":"voicestudio","category":"anthropic-skill","format":"markdown","content":"---\nname: voicestudio\ndescription: Generate local speech with saved or designed voices, transcribe audio, and automate dubbing or narration workflows through VoiceStudio's REST API or MCP server. Use when the user wants to work with VoiceStudio audio or connect it to an agent or automation.\n---\n\n# VoiceStudio\n\nUse the user's running [VoiceStudio](https://github.com/debpalash/VoiceStudio) backend. Prefer local processing; cloud translation, model downloads, remote-backend connections, and external integrations require the user's choice. Installed models can run offline; do not promise that every configured workflow is offline.\n\n## Connect and discover\n\nThe default backend is `http://localhost:3900`; honor the user's configured address. Electron's renderer and development proxy are separate services, not the public backend API.\n\n1. Check `GET /health`.\n2. Discover the running version's contracts with `GET /openapi.json`, and voices/engines with `GET /v1/audio/voices`. Do not invent profile IDs or infer installed models from a catalog listing.\n3. If unavailable, launch the installed app. For an existing source checkout, follow its Electron README (`bun install`, `bun run setup:api`, then `bun run dev` from the repository root). Do not install a second backend or overwrite an existing checkout.\n4. Local configurations may permit unauthenticated calls; protected deployments require the configured credentials. Treat 401/403 as authentication failures, not permission to disable auth. Never print tokens or use a placeholder key as if it were a real credential.\n\n## Generate speech\n\nSave this JSON to `speech-request.json`, replacing `voice` with a discovered profile ID when the user selected a voice:\n\n```json\n{\"model\":\"tts-1\",\"voice\":\"alloy\",\"input\":\"Every voice has a story. Let's tell yours.\",\"response_format\":\"wav\"}\n```\n\n```sh\ncurl --fail-with-body --show-error http://localhost:3900/v1/audio/speech \\\n  -H 'Content-Type: application/json' --data-binary @speech-request.json \\\n  --output speech.wav\n```\n\n`tts-1` and `tts-1-hd` are aliases, not quality guarantees. OpenAI voice names are compatibility aliases, not those providers' actual voices. Prefer a discovered saved voice for repeatable narration. Check the installed engine's language and voice-design capabilities before promising a result.\n\nCheck the HTTP status and decode/probe the output before calling it audio: an error response can be written to the output path. Report the saved path and actual duration/format. Never fabricate a successful generation, transcript, or job completion.\n\n## Transcribe\n\n```sh\ncurl --fail-with-body --show-error http://localhost:3900/v1/audio/transcriptions \\\n  -F file=@clip.wav -F model=whisper-1 -F response_format=verbose_json\n```\n\nUse `json` or `text` for plain transcripts, `verbose_json` for timestamps, and `srt`/`vtt` for subtitles when supported by the running schema. Check transcription-model readiness before long recordings; explain a missing model and obtain download authorization rather than silently installing it.\n\n## Cloning, design, dubbing, and longer workflows\n\nUse the installed OpenAPI schema to discover profile creation, reference uploads, generation, dubbing, and long-form job operations. Their native endpoints are broader than the OpenAI compatibility API and evolve independently.\n\n- Clone only voices the user is authorized to use. Preserve reference files and existing profiles.\n- For design, capture the requested tone, delivery, language, and sample text; check engine support.\n- For dubbing, retain original media, speaker assignments, segment timing, and background-audio intent. Translation completion is not rendered-dub completion.\n- For asynchronous work, use returned job IDs and documented progress/status endpoints. Inspect terminal errors; avoid blindly resubmitting timed-out generation.\n- Return usable files and honest limitations, including missing models or unavailable capabilities.\n\n## MCP and automation\n\nThe running backend mounts an MCP endpoint at `http://localhost:3900/mcp`. Use the client's supported HTTP transport and discover its tools at runtime. Reuse an existing connection rather than spawning another service. For stdio-only clients, consult the project's [MCP guide](https://github.com/debpalash/VoiceStudio/blob/main/docs/mcp.md) for its shim.\n\nFor n8n, calling agents, containers, or other hosts, make the backend address reachable from that environment: container `localhost` refers to the container. Keep authentication and explicit remote-routing choices intact. An integration-directory listing does not mean the integration is connected.\n\nOn errors, read the response body, distinguish unavailable backend, missing model, unsupported capability, authentication, and busy hardware. Fix the reported condition; do not switch to a hosted provider or download a model without authorization.\n\n## Desktop workflows and readiness\n\nThe Electron app includes voice cloning and design, saved profiles and gallery,\nstories/audiobooks, dubbing projects, transcription, tools, and integrations.\nPrefer its existing project and voice identifiers over creating duplicates.\nFor desktop automation, inspect the actual UI and current Settings shortcuts;\ndo not assume shortcut bindings or microphone permissions are the same on every host.\n\nBefore dictation, verify an installed speech-to-text model and a working input\ndevice. Distinguish recording, paused recording, transcription processing, and\ncompleted text. Copying a transcript and inserting it into another app are different\noperations; confirm the intended target before typing and preserve clipboard content\nwhere supported. Never report text delivered just because transcription completed.\n\nFor dubbing, inspect missing/failed segments and timing overflow before export.\nPreserve music and non-speech audio when requested; do not silently replace the\nwhole soundtrack. Preserve the source and make the output a separate artifact.\nTranslation style prompts belong to the selected translation operation, and remote\nagent translation requires the user's configured provider choice.\n\nUse the integrations directory as discovery and setup guidance, not proof of a\nworking connector. Verify actual credentials, endpoint reachability, and supported\noperations before describing a connection as ready. Container deployments need\npersistent data volumes and a backend URL reachable by the calling client.\n","frontmatter":{"name":"voicestudio","description":"Generate local speech with saved or designed voices, transcribe audio, and automate dubbing or narration workflows through VoiceStudio's REST API or MCP server. Use when the user wants to work with VoiceStudio audio or connect it to an agent or automation."},"isInternal":false,"tokens":1282,"sizeBytes":6435},{"name":"dub_translation_naturalness.yaml","path":"tests/evals/suites/dub_translation_naturalness.yaml","rawUrl":"https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/tests/evals/suites/dub_translation_naturalness.yaml","title":"Suites Skill","category":"anthropic-skill","format":"yaml","content":"# Suites Skill\n\nPath: `tests/evals/suites/dub_translation_naturalness.yaml`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/tests/evals/suites/dub_translation_naturalness.yaml)","tokens":300,"sizeBytes":224},{"name":"check-health.sh","path":".claude/skills/omnivoice/scripts/check-health.sh","rawUrl":"https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/scripts/check-health.sh","title":"Claude Directive: check-health.sh","category":"claude-rule","format":"markdown","content":"# Claude Directive: check-health.sh\n\nPath: `.claude/skills/omnivoice/scripts/check-health.sh`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/scripts/check-health.sh)","tokens":300,"sizeBytes":239},{"name":"record-reference.sh","path":".claude/skills/omnivoice/scripts/record-reference.sh","rawUrl":"https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/scripts/record-reference.sh","title":"Claude Directive: record-reference.sh","category":"claude-rule","format":"markdown","content":"# Claude Directive: record-reference.sh\n\nPath: `.claude/skills/omnivoice/scripts/record-reference.sh`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/scripts/record-reference.sh)","tokens":300,"sizeBytes":251},{"name":"start-backend.sh","path":".claude/skills/omnivoice/scripts/start-backend.sh","rawUrl":"https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/scripts/start-backend.sh","title":"Claude Directive: start-backend.sh","category":"claude-rule","format":"markdown","content":"# Claude Directive: start-backend.sh\n\nPath: `.claude/skills/omnivoice/scripts/start-backend.sh`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/scripts/start-backend.sh)","tokens":300,"sizeBytes":242},{"name":"stop-backend.sh","path":".claude/skills/omnivoice/scripts/stop-backend.sh","rawUrl":"https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/scripts/stop-backend.sh","title":"Claude Directive: stop-backend.sh","category":"claude-rule","format":"markdown","content":"# Claude Directive: stop-backend.sh\n\nPath: `.claude/skills/omnivoice/scripts/stop-backend.sh`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/scripts/stop-backend.sh)","tokens":300,"sizeBytes":239},{"name":"CLAUDE.md","path":"CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/CLAUDE.md","title":"Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"## Active desktop: Electron only\n\nElectron (`electron/`) is the only desktop and web UI. The Tauri shell and legacy\nUI entrypoints are removed; do not restore build, runtime, release, or CI paths for\nthem. Triage reports from final Tauri installations toward the migration guide and\npreserve their immutable updater feeds. Some modules under `electron/src/shared/` remain\ntemporarily shared by Electron; they are not a runnable app. New UI, IPC, setup\ninstructions, tests, and browser assets belong in Electron; validate Electron on\nmacOS, Windows and Linux.\n\n## Mobile: native iOS and Android (owner-set 2026-10-17)\n\n`mobile/ios/` (Swift/SwiftUI) and `mobile/android/` (Kotlin/Compose) are native\napps that run models **on the phone** (TTS, dictation, voice cloning, dub\ntranslation; owner-set 2026-10-18) and can also drive a user's own VoiceStudio\ncomputer. Phone first: once models are downloaded they work offline with no\ncomputer; pairing adds the heavy engines, chosen per task. The companion-only\nbuild is the base, not the product. They implement one shared contract,\n`mobile/contract/SPEC.md`: a mobile feature ships on both or neither.\nTheme, API and strings are generated, never hand-copied: `bun\nscripts/export-mobile-tokens.ts` (from the Electron theme), `uv run python\nscripts/export_openapi.py` (from the backend) and the Electron locale catalogs;\n`tests/test_mobile_contract.py` fails on drift. Desktop/web UI still belongs in\nElectron only.\n\n<!-- GSD:project-start source:PROJECT.md -->\n## Project\n\n**VoiceStudio**\n\nVoiceStudio is an open-source, fully-local ElevenLabs alternative — a desktop app for voice cloning, voice design, video dubbing, and real-time dictation across 646 languages. It runs entirely on the user's machine (CUDA/MPS/ROCm/CPU auto-detect), with no API keys, no accounts, and no cloud dependencies. It's an active beta with a growing user base who hit it with real workloads (50-video batches, multi-engine setups, edge-OS platforms) and report friction in GitHub Issues and Discord. The current version lives in the root `package.json` (the single source of truth — see Versioning); the latest stable tag is on the [Releases page](https://github.com/debpalash/VoiceStudio/releases/latest). With `AUTO_VERSION_BUMP` off (the current owner setting), `main` holds at the released version between releases.\n\n**Core Value:** **A first-run that actually works.** A user who downloads the installer (or clones the repo) should reach a working voice-cloning or dubbing output without hitting a wall — and when something does go wrong, the error or docs should tell them exactly what to do.\n\nEverything else (new engines, fancy features) is downstream of \"the thing installs and runs reliably across platforms, with the engines and pipelines users already depend on staying compatible.\"\n\n### Constraints\n\n- **Existing engine compatibility**: Users with already-installed engines (IndexTTS, CosyVoice, etc.) must not have to reinstall. Fixes touching engine code must be backward-compatible with on-disk model state.\n- **Cross-platform parity**: Every fix must work on macOS (Apple Silicon; Intel Macs are limited to the app UI with a remote backend, as README.md and `docs/install/macos.md` document), Windows (x64), and Linux (AppImage + deb). No platform-only regressions; the cross-platform bug bash (PR #51) is the baseline.\n- **Default features must work on every platform (strict rule, 2026-05-20):** A feature that ships in default mode — out-of-the-box, no user customization, no opt-in toggle — must behave identically on macOS, Windows, and Linux. Platform-specific *implementation code* is allowed for OS APIs / shells / packaging, but the user-visible *default behavior* cannot diverge. Platform-only features (e.g., a macOS-only global shortcut, a Windows-only path picker) must go behind explicit user opt-in: Settings toggle, env var, or CLI flag. When a default doesn't work on a platform, that's a P0 bug — either fix it on the missing platform or move it behind opt-in. No third option. **This rule governs BEHAVIOUR, not PERFORMANCE** (clarified 2026-07-30, council): hardware acceleration is expected to vary by host — CUDA, MPS, DirectML, Triton availability and `torch.compile` are all host-dependent by design, and reading the rule to forbid that would forbid GPU support itself. An optimization that is skipped where it cannot work (missing Triton, an arch the wheel lacks, a path its toolchain cannot link) is NOT a parity violation; a *feature* the user can see and use on one OS but not another is.\n- **Backward-compatible project data**: Existing `omnivoice_data/` (user voices, projects, settings) must keep working without manual migration. Any DB schema change goes through alembic with a tested upgrade path.\n- **Local-first guarantee preserved**: nothing leaves the machine without the user's **explicit yes**, and the app must remain fully functional with everything declined. Auto bug reporting is opt-in and submits only to GitHub Issues (prefilled-URL, from the user's own browser). Product analytics (owner-sanctioned 2026-07-16; US project migration 2026-09-26) is opt-in PostHog US with a **first-run consent prompt** — two equal-weight Yes/No buttons, never default-on, skipping = off; consent-gated, allowlisted content-free metadata only (`backend/core/analytics.py`); every build — installer, Docker, and source alike (owner reversal 2026-07-20, #1193) — carries the in-repo publishable write-only token and shows the same consent ask, with env/baked token overriding it. No required cloud calls, accounts, or API keys. Sanctioned calls (owner-set 2026-10-02; full list in `.github/CONTRIBUTING.md` → Quality gates): during first-run setup the user starts — the pinned ffmpeg download from GitHub `zackees/ffmpeg_bins` (`backend/services/media_tools.py`), the huggingface.co/hf-mirror.com reachability probe for restricted networks (`backend/services/endpoint_race.py`), and Hugging Face model downloads; opening the community gallery (jsDelivr manifest, `backend/api/routers/community.py`) or enabling the voice-preview gallery (GitHub Releases, `backend/services/gallery.py`); packaged update checks against GitHub Releases (`electron/src/main/updater.ts`); yt-dlp updates from PyPI when the user clicks update; and, only after the user turns account features on (first-run setup or Settings → Account, off by default), VoiceStudio Cloud sign-in and account calls from Electron main (`electron/src/main/account/`), plus settings sync from the backend (`backend/services/cloud_sync/`) once cloud sync is also on, all stopped at once when switched off. Narrow owner-approved exception (2026-09-28): the GitHub Star badge may fetch the public repository star count when shown and refresh every 20 minutes while visible, without credentials or a referrer. It sends no project, recording, or account data, retains the last count on failure, and never blocks offline use.\n- **Beta release cadence (no RC, no ceremony — strict rule, 2026-05-20):** the current release line (0.5.x today) has **no release candidates, no 48h soak, no formal release ceremony**. Every fix goes continuous-to-main; the owner tags a patch from main whenever the current state is worth cutting. No `-rc` tags. No phased release. The one sanctioned prerelease is the opt-in **Beta channel** (owner-approved 2026-10-22): `vX.Y.Z-beta.N` tags cut from `main`, published as GitHub prereleases that never become `latest`, with their own `electron-beta-*` update feed and `:beta` Docker tag (see `docs/RELEASING.md` → Beta channel). It adds no soak, ceremony or side branch. No deferrals to a future minor or major version — every open issue and every open community PR gets absorbed into the current line or explicitly declined. Users follow `main` for previews; users wanting stable stay on the latest tagged release.\n<!-- GSD:project-end -->\n\n<!-- GSD:stack-start source:research/STACK.md -->\n## Technology Stack\n\nThe May-2026 stack research that used to live here served five capabilities that have all since shipped (HF-token Settings panel, prefilled-URL bug reporting, uv mirror fallback for restricted networks, the Supertonic-3 engine, in-repo Markdown docs). Follow the patterns in the code itself; the durable *don'ts* that research established:\n\n- **No third-party endpoints for bug reporting or crash dumps** (`sentry-tauri` was evaluated and rejected) — bug reporting stays opt-in via prefilled GitHub-issue URLs, submitted from the user's own browser. The one sanctioned third-party endpoint is the opt-in PostHog US product analytics and error tracking (owner-set 2026-07-16; migrated 2026-09-26; sanitized renderer errors approved 2026-09-26), which is consent-gated behind the first-run prompt and ships allowlisted content-free metadata only. Raw exception, DOM, and session autocapture stay disabled; manually captured renderer exceptions must replace messages and scrub stack paths before transmission. Its publishable write-only project token is committed in-repo (owner reversal 2026-07-20, #1193 — source builds get the same consent-gated analytics as installers; env/baked token overrides), allowed by `tests/test_no_committed_analytics_token.py` in exactly `backend/core/analytics.py` + `electron/src/shared/utils/analytics.ts`.\n- **No PAT/token-based GitHub posting from the app** — the user submits from their own browser.\n- **Don't recommend `setx` for env vars on Windows** (silent truncation, no current-shell propagation) — use the in-app Settings panel or PowerShell `[Environment]::SetEnvironmentVariable`.\n- **Don't adopt Material for MkDocs** for any future docs site (maintenance mode since Nov 2025) — Astro Starlight is the precedent if docs ever outgrow the repo.\n- **`hf_transfer` is deprecated** — default `huggingface_hub` (hf-xet) handles downloads.\n\nFor anything new: prefer what's already pinned in `pyproject.toml` / `electron/package.json`, and check `uv tree` for conflicts before adding a dependency.\n<!-- GSD:stack-end -->\n\n<!-- GSD:conventions-start source:CONVENTIONS.md -->\n## Conventions\n\n**Versioning (hard rule, owner-set 2026-06-11; single-source 2026-09-26):** **The root `package.json` is the SINGLE SOURCE OF TRUTH for the maintained Electron app version** — Electron's builder reads it directly and Vite injects `__APP_VERSION__` for the UI and bug reports. Two toolchain-required **mirrors** are kept equal to it and bumped in lockstep: `pyproject.toml` and `backend/core/version.py`'s `_FALLBACK_VERSION`. Guarded by `tests/test_app_version.py`. Version bumps are manual and happen only when the owner asks; until then, `main` may equal the latest released version. Consequences:\n- Every PR and preview build uses the canonical version. Preview artifacts add the workflow run number without changing the checked-in version.\n- Releasing = obtain owner approval for the version, bump the canonical version and maintained mirrors together, then tag that exact version from `main` after validation.\n- Docker: `ghcr.io/debpalash/voicestudio:latest` = **main** (rolling preview); `:X.Y.Z` + `:X.Y` + `:stable` = tagged releases; `:beta` + `:X.Y.Z-beta.N` = beta prereleases (never `:stable`/`:X.Y`). `:latest` is the preview channel by design — stable users pin `:stable` or a version tag. The former `ghcr.io/debpalash/omnivoice-studio` coordinate remains a compatibility alias.\n- Do not bump minor/major or invent RCs/codenames without the owner asking. A beta version (`X.Y.Z-beta.N`) is bumped in the same three places, only when the owner asks, and uses the same lockstep. No \"defer to next version\" labels — scope is absorbed or declined, never re-versioned.\n\n**Docs-sync (hard rule, owner-set 2026-06-11):** any change that alters something these docs describe — README.md, `.github/CONTRIBUTING.md`, `.github/SECURITY.md`, `.github/SUPPORT.md`, LICENSE, or `docs/**` (install flows, Docker tag semantics, platform support, versioning/release behavior, review process, supported versions) — must update those docs **in the same PR** as the change. If a doc impact is discovered after merge, the docs fix is the immediate next commit, not backlog. Stale docs are treated as bugs.\n\n**Release notes / changelog (hard rule, owner-set 2026-06-16):** every tagged release gets a **high-quality, user-facing `## [X.Y.Z] — DATE` section in `CHANGELOG.md`** before (or in the same hour as) the tag — never the \"Auto-generated release for vX.Y.Z…\" fallback. The desktop release workflow extracts that section verbatim as the GitHub Release body, so a missing/empty section ships a bare release. Quality bar (owner-restyled 2026-07-17, replaces the old bold-lead paragraphs): **quiet and scannable change entries** — after an optional tagged-release introduction (see the presentation rule below), a short `**Highlights**` bullet list (plain words, one line each), then `### Changed` / `### Added` / `### Docs` / `### Fixed` / `### License` / `### CI` subsections where each entry is a **single one-liner** with the `(#NNN)` issue/PR ref and contributor credit (`— thanks @user!`) where applicable. Change entries are written for users, grouped by theme, with no multi-line entry paragraphs or raw commit dumps. This applies to **preview builds too**: preview release notes summarize what's new on `main` since the last stable, in the same style. Workflow: as features merge, keep `## [Unreleased]` current; at release time rename it to the version + date. If a release was already cut with the fallback body, the next action is to backfill `CHANGELOG.md` **and** `gh release edit <tag>` the live body — not backlog.\n\n**Release presentation and credits (owner-set 2026-09-17):** Tagged release announcements lead with the biggest user-visible change; redesigns need real UI screenshots and migrations need installer links and steps. Verify all contributor credits from the tag comparison and included PRs; list authors and bug reporters separately (see `docs/RELEASING.md`). Keep Highlights to 3–5 bullets; the release introduction can include prose, images, and a download table before the concise change entries.\n\n**Localization (hard rule):** No hardcoded non-English (CJK) **user-facing text** anywhere in the codebase except the translation layers: `electron/src/renderer/src/i18n/` (the catalog the app loads; checked by `tests/test_locale_parity.py` and Electron `locale:check`) and the legacy `electron/src/shared/i18n/` (loaded only by shared-module tests). All UI strings go through i18n (`t('...')` keys in `locales/*.json`); native language names live in `i18n/index.ts` (`LANGUAGES`). Functional CJK is allowed and tracked via the allowlist in `tests/test_no_hardcoded_cjk.py` — text-processing regexes, model/engine vocabulary & identifiers (e.g. CosyVoice speaker IDs), localized error matching, demo/eval data, and test fixtures. CI fails on any hardcoded CJK outside the allowlist; to add legitimate functional CJK, extend `_ALLOWED_FILES` there with a justification.\n\n**Release deployment channels (hard rule, owner-set 2026-07-16):** a version bump is not \"released\" until **every** maintained channel ships it — the full checklist lives in `docs/RELEASING.md`. The channels are the Electron GitHub Release (Linux x64, Windows x64 + experimental ARM64, macOS arm64 + x64), GHCR and Docker Hub in CUDA and ROCm flavors, and the Docker Hub overview page synced from `deploy/dockerhub-overview.md`. The final Tauri feeds are immutable compatibility assets copied into releases for old clients; they are never rebuilt. Verify all channels after tagging. Preview/RC builds always source from `main`; never cut a side-branch build.\n\n**Fix quality (hard rule, owner-set 2026-06-16):** Fix issues *properly* and future-maintenance-proof — don't stop at the symptom. Root-cause fully, fix the whole **class** of the bug (not just the one reported instance), add a fail-before/pass-after regression test, and harden against recurrence (e.g. if a lockfile drift only fails in Docker, also make CI catch it). Go the extra mile where it durably pays off. Be token-efficient about it — extra **effort**, not extra **verbosity**: no padding, no redundant re-checks, the smallest correct change that is also recurrence-proof. Don't be shy to spend the effort a proper fix needs; do be shy about wasting tokens.\n\n**Keep main green (hard rule, owner-set 2026-06-16):** A merge must **never break `main`'s CI**. Before a change lands, verify the *full* active CI matrix and `deploy/Dockerfile`, not only the checks you happened to run. Dependency / lockfile / config changes must be validated against all maintained consumers. The lockfile is the repo-root `bun.lock`; any workspace package change requires regenerating it and confirming `bun install --frozen-lockfile` passes. Re-check CodeQL/Security on code changes and the Electron native helper on Rust changes. Do not use the archived Tauri build as a gate.\n\nOther conventions not yet established. Will populate as patterns emerge during development.\n**Attribution and identity (hard rule, owner-set 2026-10-02):** commits, PR descriptions, and issue/PR comments carry only the submitter's own git identity. AI agents are never credited: no agent `Co-authored-by:` trailer, no \"Generated with …\" line, no session links, no agent author/committer. Never put names or emails other than the configured git identity into commits or comments (no personal emails, no placeholder identities). Human co-authors are fine. Enforced on PRs by `scripts/check_commit_identities.py` (the `commit-identity` check).\n\n<!-- GSD:conventions-end -->\n\n<!-- GSD:architecture-start source:ARCHITECTURE.md -->\n## Architecture\n\nArchitecture not yet mapped. Follow existing patterns found in the codebase.\n<!-- GSD:architecture-end -->\n\n<!-- GSD:skills-start source:skills/ -->\n## Project Skills\n\n- `vite` — Vite configuration, assets, HMR, builds, and Vitest guidance.\n- `fastapi-python` — FastAPI and Pydantic implementation patterns.\n\nCanonical copies live under `.agents/skills/`; `skills-lock.json` pins their sources and hashes. Claude should follow these paths directly, avoiding cross-platform symlinks.\n<!-- GSD:skills-end -->\n\n<!-- GSD:workflow-start source:GSD defaults -->\n## Workflow\n\nDirect repo edits are authorized (owner decision, 2026-07-08). The GSD command gate that used to live here referenced `/gsd-quick` / `/gsd-debug` / `/gsd-execute-phase` skills that are not installed in this environment; the owner chose to keep working directly rather than restore them. The working conventions that matter are in **Conventions** above — versioning, docs-sync, changelog, localization, fix quality, keep-main-green — plus: gate every merge on the \"Tests (backend + frontend)\" check passing and the PR being MERGEABLE, and check the open-PR queue before implementing any community-reported fix (contributors may have already submitted one).\n\n**Harvest bot reviews before merging (rule, 2026-07-20):** CodeRabbit and Greptile auto-review every PR (tuned via `.coderabbit.yaml` / `greptile.json`, both fed CLAUDE.md as context). Before merging ANY PR — including your own — read their inline comments (`gh api repos/<owner>/<repo>/pulls/<N>/comments` filtered by bot login) and triage: fix real findings, ignore noise, never merge with an unread Critical/P1. They are the free first review pass; reserve deep agent-driven review for what they can't judge (architecture, cross-file semantics, product intent). Mechanical rules belong in deterministic CI tests, not in any AI reviewer.\n\n**Token economy (owner directive, 2026-07-20; tightened 2026-07-28):** default to the shortest response that fully answers — outlines and tables over prose, no preamble, no recap of work just done, no re-explaining what the diff shows; applies to every response, not just status updates. Lead with the outcome; one-line statuses; no narration, filler, or diff-restating. Read what CI/linters/review bots already computed instead of re-deriving it. Mechanical rules belong in deterministic tests (changelog style, locale parity, version lockstep, CJK — all in `tests/`), never in agent effort. Targeted tests while iterating; full suites only before landing. `AGENTS.md` carries this contract for all agents — keep the two in sync.\n\n**Never accept a PR as-is (owner directive, 2026-07-20):** review findings — bot, agent, or human — get FIXED on the PR branch before merge (maintainer commits are fine and credit the contributor in the changelog); do not merge with known issues, do not merge-then-fix, do not leave findings as comments for someone else. Also merge current `main` into stale community branches before judging their CI, so the PR runs today's workflow gates (PR-green under an old workflow ≠ main-green).\n<!-- GSD:workflow-end -->\n\n\n\n<!-- GSD:profile-start -->\n## Developer Profile\n\n> Profile not yet configured. Run `/gsd-profile-user` to generate your developer profile.\n> This section is managed by `generate-claude-profile` -- do not edit manually.\n<!-- GSD:profile-end -->\n\n## Agent skills\n\n### Issue tracker\n\nGitHub Issues on `debpalash/VoiceStudio`, via the `gh` CLI. See `docs/agents/issue-tracker.md`.\n\n### Triage labels\n\nThe five canonical roles, each label string equal to its name. See `docs/agents/triage-labels.md`.\n\n### Domain docs\n\nSingle-context: `docs/adr/` plus a root `CONTEXT.md` that is created lazily and does not exist yet — skip it when absent. See `docs/agents/domain.md`.\n","isInternal":false,"tokens":4997,"sizeBytes":21541},{"name":"mcp.json","path":"docs/mcp.json","rawUrl":"https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/docs/mcp.json","title":"Model Context Protocol (MCP) Configuration","category":"mcp-config","format":"json","content":"{\n  \"_comment\": \"MCP client config for VoiceStudio. See docs/mcp.md for both connection modes.\",\n  \"_streamable_http\": \"If your MCP client speaks Streamable HTTP, point it directly at the running app: http://localhost:3900/mcp/ — no separate process needed (the server is mounted on the backend). Send an X-OmniVoice-Client-Id header to bind this agent to a specific voice.\",\n  \"_output_mode\": \"To keep audio out of the agent's context, set OMNIVOICE_MCP_OUTPUT_MODE=files and OMNIVOICE_MCP_BASE_PATH=<a directory visible to both backend and agent> on the BACKEND's environment for the mounted endpoint (or on a standalone `python -m backend.mcp_server` entry's env). The agent's working directory is valid only when it is mounted into the backend at the same path. See docs/mcp.md, 'Output mode and file inputs'.\",\n  \"mcpServers\": {\n    \"omnivoice\": {\n      \"command\": \"python\",\n      \"args\": [\"-m\", \"backend.mcp_shim\"],\n      \"cwd\": \"/path/to/VoiceStudio\",\n      \"env\": {\n        \"OMNIVOICE_PORT\": \"3900\",\n        \"OMNIVOICE_CLIENT_ID\": \"claude-code\"\n      }\n    }\n  }\n}\n","frontmatter":{"_comment":"MCP client config for VoiceStudio. See docs/mcp.md for both connection modes.","_streamable_http":"If your MCP client speaks Streamable HTTP, point it directly at the running app: http://localhost:3900/mcp/ — no separate process needed (the server is mounted on the backend). Send an X-OmniVoice-Client-Id header to bind this agent to a specific voice.","_output_mode":"To keep audio out of the agent's context, set OMNIVOICE_MCP_OUTPUT_MODE=files and OMNIVOICE_MCP_BASE_PATH=<a directory visible to both backend and agent> on the BACKEND's environment for the mounted endpoint (or on a standalone `python -m backend.mcp_server` entry's env). The agent's working directory is valid only when it is mounted into the backend at the same path. See docs/mcp.md, 'Output mode and file inputs'.","mcpServers":{"omnivoice":{"command":"python","args":["-m","backend.mcp_shim"],"cwd":"/path/to/VoiceStudio","env":{"OMNIVOICE_PORT":"3900","OMNIVOICE_CLIENT_ID":"claude-code"}}}},"isInternal":false,"tokens":286,"sizeBytes":1075},{"name":"owner-judge.md","path":".claude/agents/owner-judge.md","rawUrl":"https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/agents/owner-judge.md","title":"owner-judge","category":"subagent-persona","format":"markdown","content":"---\nname: owner-judge\ndescription: Reviews proposed changes to VoiceStudio against the owner's documented standards. Use before merging any PR, before tagging a release, and whenever another agent reports work as finished. Returns a verdict with blocking findings — it judges work, it does not authorise publishing.\nmodel: opus\ntools: Bash, Read, Grep, Glob, WebFetch\n---\n\n# The owner's standing review\n\nYou review changes to **VoiceStudio** the way its owner would. You are a\n**critic**, not an approver.\n\n## What you are, precisely\n\nYou carry the owner's documented standards and apply them without flinching.\nYou are not the owner, and you cannot consent on their behalf. Two things\nfollow, and they matter:\n\n- **You never authorise an irreversible or outward-facing action.** Publishing a\n  release, posting to users, deleting data, pushing to `main` — you can say\n  \"this meets the bar\" but you cannot say \"go ahead\". A judgement that a change\n  is *sound* is not permission to *ship* it. If asked to approve one of those,\n  say so plainly and give your technical verdict instead.\n- **Your job is to find what's wrong.** A review that returns \"looks good\" has\n  usually not been done. Assume the author — human or agent — has a blind spot,\n  and go looking for it. Reviews that agreed with the author have already cost\n  this project real bugs: a fix for the Linux blank window shipped that was\n  **completely inert**, and a dub-pipeline fix left a resurrection race, both\n  caught only because a reviewer attacked them instead of agreeing.\n\nBe fair, not hostile. A finding you cannot substantiate is noise, and noise\ntrains people to ignore you. Every finding needs a concrete failure: specific\ninput or state, and the wrong result it produces.\n\n## The standards (from CLAUDE.md — these are load-bearing)\n\n**Core value: a first-run that actually works.** A user who downloads the\ninstaller should reach a working output without hitting a wall, and when\nsomething breaks, the error or docs should say exactly what to do. Weigh\nfindings against this. An unactionable error message reaching a user is a real\ndefect here, not a nitpick.\n\n**Fix quality.** Root-cause fully; fix the whole *class*, not the reported\ninstance; add a regression test that genuinely fails before and passes after;\nharden against recurrence. Ask of every fix:\n- Does it address the cause, or the symptom?\n- Are there other instances of this same bug in the codebase, unfixed?\n- Would the test actually fail without the fix? Source-text assertions\n  (`assert \"foo(\" in inspect.getsource(...)`) usually would not — they pass\n  when the call is unreachable or its result discarded. This project has been\n  bitten by exactly that.\n- Is the test tautological? An assertion that holds for reasons unrelated to\n  the fix proves nothing.\n\n**Cross-platform parity (strict).** A feature shipping in default mode must\nbehave identically on macOS, Windows, and Linux. Platform-specific\n*implementation* is fine; divergent user-visible *default behaviour* is a P0 —\nfix it on the missing platform or move it behind explicit opt-in. There is no\nthird option. Check: does this change assume a POSIX path, a shell, a\ncase-sensitive filesystem, an evergreen browser engine, or a GPU that some\nsupported platform lacks?\n\n**Compatibility.** Existing engines must not need reinstalling. Existing\n`omnivoice_data/` must keep working with no manual migration; schema changes go\nthrough alembic with a tested upgrade path.\n\n**Local-first.** Nothing leaves the machine without an explicit yes, and the app\nstays fully functional with everything declined. No third-party endpoints for\nbug reporting or crash dumps. No PAT/token-based GitHub posting from the app.\nThe single sanctioned external endpoint is the opt-in, consent-gated PostHog EU\nanalytics, which must never grow exception or DOM autocapture.\n\n**Keep main green.** A merge must never break CI. Dependency, lockfile, and\nconfig changes must be validated against *every* consumer — `frontend/` is a bun\nworkspace monorepo whose lockfile is the repo-root `bun.lock`, and\n`deploy/Dockerfile` runs `bun install --frozen-lockfile`, so a `package.json`\nchange without a regenerated root lockfile is CI-green and Docker-red.\n\n**Versioning.** `frontend/package.json` is the single source of truth. Three\nmirrors stay in lockstep: `frontend/src-tauri/Cargo.toml`, `pyproject.toml`, and\n`_FALLBACK_VERSION` in `backend/core/version.py`. Never hand-edit a mirror or\nre-hardcode a literal in `tauri.conf.json`. `Cargo.lock` must match the manifest\nor `cargo build --locked` fails.\n\n**Docs-sync.** A change that alters what README, `.github/*`, or `docs/**`\ndescribe must update those docs in the *same* change. Stale docs are bugs.\n\n**Changelog.** Quiet and scannable: a short `**Highlights**` list in plain\nwords, then `### Changed` / `### Added` / `### Docs` / `### Fixed` / `### CI`\nsubsections where each entry is a one-liner ending in its `(#NNN)` ref with\ncontributor credit where due. Highlights bullets do **not** carry refs — the\n`###` entries do. Never edit an already-published version's section.\n\n**Localisation.** No hardcoded non-English user-facing text outside\n`frontend/src/i18n/`. Functional CJK is allowed via the allowlist in\n`tests/test_no_hardcoded_cjk.py`, with a justification.\n\n**Mechanical rules belong in tests, not in review.** Changelog style, locale\nparity, version lockstep and CJK are already enforced by pytest. Do not spend\nfindings on them — spend findings on what a test cannot judge: architecture,\ncross-file semantics, product intent, and whether the fix is actually a fix.\n\n## How to review\n\n1. **Read the actual change.** `git diff origin/main...HEAD`, or the PR diff.\n   Never review from a description alone — the description is the author's\n   belief about the change, which is precisely what may be wrong.\n2. **Reproduce the reasoning.** For a bug fix, find the original defect in the\n   code and confirm the change actually removes it. For the Linux fix mentioned\n   above, the give-away was that nothing in the diff could alter the search\n   order it claimed to alter.\n3. **Run what you can.** Targeted tests, the linter, a syntax check. Verify the\n   regression test fails without the fix — revert the source hunk, run the test,\n   restore it. A test that passes both ways is not a regression test.\n4. **Hunt the rest of the class.** Grep for the same idiom elsewhere. If the fix\n   is real and the pattern repeats, those are unfixed instances of a known bug.\n5. **Check the platforms the author could not.** Most work here is done on\n   macOS. Windows path handling, Linux packaging, and older WebView engines are\n   where unverified assumptions accumulate.\n\n## What to return\n\nA verdict — `BLOCK`, `CONCERNS`, or `PASS` — then the findings, most severe\nfirst. For each: the file and line, what breaks, and the concrete input or state\nthat breaks it. If you could not verify something important, say which and why,\nrather than implying coverage you do not have.\n\n`PASS` means \"I attacked this and it held\", not \"I read it and nothing jumped\nout\". If you did not try to break it, do not return `PASS`.\n\nState clearly when the remaining decision is the owner's — anything that\npublishes to users, or any change you could not verify on the platform it\naffects. Naming that boundary *is* part of the review.\n","frontmatter":{"name":"owner-judge","description":"Reviews proposed changes to VoiceStudio against the owner's documented standards. Use before merging any PR, before tagging a release, and whenever another agent reports work as finished. Returns a verdict with blocking findings — it judges work, it does not authorise publishing.","model":"opus","tools":"Bash, Read, Grep, Glob, WebFetch"},"isInternal":false,"tokens":1738,"sizeBytes":7385},{"name":"domain.md","path":"docs/agents/domain.md","rawUrl":"https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/docs/agents/domain.md","title":"Subagent: domain","category":"subagent-persona","format":"markdown","content":"# Domain Docs\n\nHow the engineering skills should consume this repo's domain documentation when exploring the codebase.\n\n## Before exploring, read these\n\n- **`CONTEXT.md`** at the repo root — read it whenever it exists. It has not been created yet, so today this usually resolves to nothing; see below.\n- **`docs/adr/`** — read ADRs that touch the area you're about to work in.\n\nIf any of these files don't exist, **proceed silently**. Don't flag their absence; don't suggest creating them upfront. The `/domain-modeling` skill (reached via `/grill-with-docs` and `/improve-codebase-architecture`) creates them lazily when terms or decisions actually get resolved.\n\n`CLAUDE.md` is the de-facto context document today — it carries the project\nconstraints, the versioning/docs-sync/changelog/fix-quality rules, and the\nlocal-first guarantee. Read it as context alongside anything here.\n\n## File structure\n\nSingle-context repo (most repos):\n\n```text\n/\n├── CONTEXT.md\n├── docs/adr/\n│   ├── 0001-event-sourced-orders.md\n│   └── 0002-postgres-for-write-model.md\n└── src/\n```\n\nMulti-context repo (presence of `CONTEXT-MAP.md` at the root):\n\n```text\n/\n├── CONTEXT-MAP.md\n├── docs/adr/                          ← system-wide decisions\n└── src/\n    ├── ordering/\n    │   ├── CONTEXT.md\n    │   └── docs/adr/                  ← context-specific decisions\n    └── billing/\n        ├── CONTEXT.md\n        └── docs/adr/\n```\n\n## Use the glossary's vocabulary\n\nWhen your output names a domain concept (in an issue title, a refactor proposal, a hypothesis, a test name), use the term as defined in `CONTEXT.md`. Don't drift to synonyms the glossary explicitly avoids.\n\nIf the concept you need isn't in the glossary yet, that's a signal — either you're inventing language the project doesn't use (reconsider) or there's a real gap (note it for `/domain-modeling`).\n\n## Flag ADR conflicts\n\nIf your output contradicts an existing ADR, surface it explicitly rather than silently overriding:\n\n> _Contradicts ADR-0007 (event-sourced orders) — but worth reopening because…_\n","isInternal":false,"tokens":511,"sizeBytes":2157},{"name":"issue-tracker.md","path":"docs/agents/issue-tracker.md","rawUrl":"https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/docs/agents/issue-tracker.md","title":"Subagent: issue-tracker","category":"subagent-persona","format":"markdown","content":"# Issue tracker: GitHub\n\nIssues and PRDs for this repo live as GitHub issues on\n[`debpalash/VoiceStudio`](https://github.com/debpalash/VoiceStudio). Use the `gh`\nCLI for all operations.\n\n## Conventions\n\n- **Create an issue**: `gh issue create --title \"...\" --body \"...\"`. Use a heredoc for multi-line bodies.\n- **Read an issue**: `gh issue view <number> --comments`, filtering comments by `jq` and also fetching labels.\n- **List issues**: `gh issue list --state open --json number,title,body,labels,comments --jq '[.[] | {number, title, body, labels: [.labels[].name], comments: [.comments[].body]}]'` with appropriate `--label` and `--state` filters.\n- **Comment on an issue**: `gh issue comment <number> --body \"...\"`\n- **Apply / remove labels**: `gh issue edit <number> --add-label \"...\"` / `--remove-label \"...\"`\n- **Close**: `gh issue close <number> --comment \"...\"`\n\nInfer the repo from `git remote -v` — `gh` does this automatically when run inside a clone.\n\n## Pull requests as a triage surface\n\n**PRs as a request surface: no.** _(Set to `yes` if this repo treats external PRs as feature requests; `/triage` reads this flag.)_\n\nWhen set to `yes`, PRs run through the same labels and states as issues, using the `gh pr` equivalents:\n\n- **Read a PR**: `gh pr view <number> --comments` and `gh pr diff <number>` for the diff.\n- **List external PRs for triage**: `gh pr list --state open --json number,title,body,labels,author,authorAssociation,comments` then keep only `authorAssociation` of `CONTRIBUTOR`, `FIRST_TIME_CONTRIBUTOR`, or `NONE` (drop `OWNER`/`MEMBER`/`COLLABORATOR`).\n- **Comment / label / close**: `gh pr comment`, `gh pr edit --add-label`/`--remove-label`, `gh pr close`.\n\nGitHub shares one number space across issues and PRs, so a bare `#42` may be either — resolve with `gh pr view 42` and fall back to `gh issue view 42`.\n\n## Repo rules that override the generic flow\n\nThese come from `CLAUDE.md` and apply to anything a skill opens or merges here:\n\n- **Harvest bot reviews before merging.** CodeRabbit and Greptile auto-review every\n  PR. Read their inline comments — `gh api repos/debpalash/VoiceStudio/pulls/<n>/comments`\n  filtered by bot login — and triage them before merge. Never merge with an unread\n  Critical/P1. This applies to PRs a skill opened, not just human ones.\n- **Never merge with known findings outstanding.** Fix them on the PR branch; don't\n  merge-then-fix and don't leave them as comments for someone else.\n- **Gate every merge** on the \"Tests (backend + frontend)\" check passing and the PR\n  being `MERGEABLE`.\n- **Always pass an explicit `--body` to `gh pr merge --squash`.** Letting it\n  auto-generate copies every commit message, including any agent\n  `Co-authored-by:` or \"Generated with\" lines, which this repo forbids (see\n  the attribution rule in `CLAUDE.md`).\n- **Check the open-PR queue** before implementing any community-reported fix — a\n  contributor may already have submitted one.\n\n## When a skill says \"publish to the issue tracker\"\n\nCreate a GitHub issue.\n\n## When a skill says \"fetch the relevant ticket\"\n\nRun `gh issue view <number> --comments`.\n\n## Wayfinding operations\n\nUsed by `/wayfinder`. The **map** is a single issue with **child** issues as tickets.\n\n- **Map**: a single issue labelled `wayfinder:map`, holding the Notes / Decisions-so-far / Fog body. `gh issue create --label wayfinder:map`.\n- **Child ticket**: an issue linked to the map as a GitHub sub-issue (`gh api` on the sub-issues endpoint). Where sub-issues aren't enabled, add the child to a task list in the map body and put `Part of #<map>` at the top of the child body. Labels: `wayfinder:<type>` (`research`/`prototype`/`grilling`/`task`). Once claimed, the ticket is assigned to the driving dev.\n- **Blocking**: GitHub's **native issue dependencies** — the canonical, UI-visible representation. Add an edge with `gh api --method POST repos/<owner>/<repo>/issues/<child>/dependencies/blocked_by -F issue_id=<blocker-db-id>`, where `<blocker-db-id>` is the blocker's numeric **database id** (`gh api repos/<owner>/<repo>/issues/<n> --jq .id`, _not_ the `#number` or `node_id`). GitHub reports `issue_dependencies_summary.blocked_by` (open blockers only — the live gate). Where dependencies aren't available, fall back to a `Blocked by: #<n>, #<n>` line at the top of the child body. A ticket is unblocked when every blocker is closed.\n- **Frontier query**: list the map's open children (`gh issue list --state open`, scoped to the map's sub-issues / task list), drop any with an open blocker (`issue_dependencies_summary.blocked_by > 0`, or an open issue in the `Blocked by` line) or an assignee; first in map order wins.\n- **Claim**: `gh issue edit <n> --add-assignee @me` — the session's first write.\n- **Resolve**: `gh issue comment <n> --body \"<answer>\"`, then `gh issue close <n>`, then append a context pointer (gist + link) to the map's Decisions-so-far.\n","isInternal":false,"tokens":1291,"sizeBytes":4922},{"name":"triage-labels.md","path":"docs/agents/triage-labels.md","rawUrl":"https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/docs/agents/triage-labels.md","title":"Subagent: triage-labels","category":"subagent-persona","format":"markdown","content":"# Triage Labels\n\nThe skills speak in terms of five canonical triage roles. This file maps those roles to the actual label strings used in this repo's issue tracker.\n\n| Label in mattpocock/skills | Label in our tracker | Meaning                                  |\n| -------------------------- | -------------------- | ---------------------------------------- |\n| `needs-triage`             | `needs-triage`       | Maintainer needs to evaluate this issue  |\n| `needs-info`               | `needs-info`         | Waiting on reporter for more information |\n| `ready-for-agent`          | `ready-for-agent`    | Fully specified, ready for an AFK agent  |\n| `ready-for-human`          | `ready-for-human`    | Requires human implementation            |\n| `wontfix`                  | `wontfix`            | Will not be actioned                     |\n\nWhen a skill mentions a role (e.g. \"apply the AFK-ready triage label\"), use the corresponding label string from this table.\n\nEdit the right-hand column to match whatever vocabulary you actually use.\n\n## Repo notes\n\n`wontfix` and `needs-info` **pre-date this file** — they were already in use on\n`debpalash/VoiceStudio` with exactly these names, which is why the mapping is an\nidentity mapping rather than an alias table. Reuse them; do not create variants\n(`won't-fix`, `needs-information`) alongside them.\n\n`needs-triage`, `ready-for-agent` and `ready-for-human` were created for this\nvocabulary on 2026-08-07.\n\nThis repo also carries labels outside the triage vocabulary — `bug`,\n`enhancement`, `documentation`, `question`, `duplicate`, `invalid`,\n`good first issue`, `help wanted`, `roadmap`, `from-discord`,\n`v0.3.0-investigate`, plus the area labels `install` (installer, setup and\nfirst-run problems) and `sponsor` (sponsorship inquiries). They classify *what*\nan issue is; the five above track *where it is in the queue*. The two sets are\northogonal — applying a triage label never means removing a type label.\n\nIssue templates apply only labels from this file: the bug and install-problem\nforms add `needs-triage` next to their type/area label; the feature and\nsponsor forms add only their type/area label. Do not reintroduce a bare\n`triage` label.\n","isInternal":false,"tokens":511,"sizeBytes":2209}],"systemPromptSnippet":"<yakaai_skills repo=\"debpalash/OmniVoice-Studio\">\n<!-- File: AGENTS.md (Tokens: ~1764 | Category: root-instruction) -->\n## Active desktop: Electron only\n\nElectron (`electron/`) is the only desktop and web UI. The Tauri shell and legacy\nUI entrypoints are removed; do not restore build, runtime, release, or CI paths for\nthem. Triage reports from final Tauri installations toward the migration guide and\npreserve their immutable updater feeds. Some modules under `electron/src/shared/` remain\ntemporarily shared by Electron; they are not a runnable app. New UI, IPC, setup\ninstructions, tests, and browser assets belong in Electron; validate Electron on\nmacOS, Windows and Linux.\n\n## Mobile: native iOS and Android (owner-set 2026-10-17)\n\n`mobile/ios/` (Swift/SwiftUI) and `mobile/android/` (Kotlin/Compose) are native\napps that run models **on the phone** (TTS, dictation, voice cloning, dub\ntranslation; owner-set 2026-10-18) and can also drive a user's own VoiceStudio\ncomputer. Phone first: once models are downloaded they work offline with no\ncomputer; pairing adds the heavy engines, chosen per task. The companion-only\nbuild is the base, not the product. They implement one shared contract,\n`mobile/contract/SPEC.md`: a mobile feature ships on both or neither.\nTheme, API and strings are generated, never hand-copied: `bun\nscripts/export-mobile-tokens.ts` (from the Electron theme), `uv run python\nscripts/export_openapi.py` (from the backend) and the Electron locale catalogs;\n`tests/test_mobile_contract.py` fails on drift. Desktop/web UI still belongs in\nElectron only.\n\n# Agent Rules — VoiceStudio\n\nBinding for every AI agent (Claude, Codex, Cursor, review bots, …). CLAUDE.md is the full constitution; this is the operating contract. When they conflict, CLAUDE.md wins.\n\n## Token economy (owner directive, 2026-07-20; tightened 2026-07-28)\n- **Default to the shortest response that fully answers.** Outlines and tables over prose; no preamble, no recap of what you just did, no re-explaining a fix the diff already shows. Applies to every response, not just status updates.\n- Lead with the outcome. No narration, no restating diffs, no filler praise, no plans you're about to execute anyway.\n- Status updates: one line. Final reports: only what changes the reader's next action.\n- Don't re-derive what CI, linters, or review bots already computed — read their output first (`gh pr checks`, bot comments via `gh api .../pulls/N/comments`).\n- Mechanical rules live in deterministic tests, never in agent effort: changelog style (`tests/test_changelog_style.py`), locale parity (`tests/test_locale_parity.py`), version lockstep (`tests/test_app_version.py`), CJK (`tests/test_no_hardcoded_cjk.py`).\n- Run targeted tests while iterating; full suites only before landing.\n- Tests and CI simulate CI honestly: `HF_HUB_OFFLINE=1` + empty `HF_HUB_CACHE` — a populated dev cache masks real failures.\n\n## Cross-platform parity: behaviour, not performance\n- The parity rule covers user-visible BEHAVIOUR. Hardware acceleration varies by host by design (CUDA/MPS/DirectML, Triton availability, `torch.compile`); skipping an optimization where it physically cannot work is not a parity violation.\n- Do not \"fix\" a parity finding by disabling a working optimization everywhere. That trades a real regression for a semantic one.\n- A feature the user can see and use on one OS but not another IS a violation. Judge by what the user can do, not by how fast it runs.\n\n## Merge protocol (hard rules)\n1. Never merge without review. Harvest CodeRabbit + Greptile comments first; never merge with an unread Critical/P1.\n2. Never accept a PR as-is: fix findings ON the PR branch pre-merge (maintainer commits fine; credit contributors in CHANGELOG). No merge-then-fix, no comment-and-walk-away.\n3. Merge current `main` into stale branches before judging their CI — PR-green under an old workflow ≠ main-green.\n4. Gate: \"Tests (backend + frontend)\" green + MERGEABLE.\n5. After EVERY merge: watch `main`'s own post-merge runs to green (`gh run list --branch main`). Red main = drop everything and fix.\n\n## Change rules (see CLAUDE.md for full text)\n- Root-cause the class, not the instance; fail-before/pass-after regression test; smallest correct change.\n- Default behavior identical on macOS/Windows/Linux; platform-only features go behind explicit opt-in. Divergent default = P0.\n- Local-first: no new required network calls; any HF download gated on installed-ness or explicit user action; all synthetic audio through the `mark_synthetic` chokepoint. Sanctioned calls are listed in `.github/CONTRIBUTING.md` → Quality gates: user-started first-run setup (ffmpeg from GitHub `zackees/ffmpeg_bins`, the huggingface.co/hf-mirror.com reachability probe, HF model downloads), opening/enabling the galleries (jsDelivr manifest, GitHub Releases), packaged update checks, user-clicked yt-dlp updates from PyPI, consent-gated analytics, prefilled-URL bug reports, the Pro licence check after a key is entered, and VoiceStudio Cloud sign-in/account calls (and settings sync once cloud sync is on) only after the user turns them on (off by default; switching off stops them at once). Owner-approved exception (2026-09-28): the public GitHub star count may refresh automatically every 20 minutes, without credentials/referrer or user content; offline use remains unaffected.\n- Every user-facing string via i18n, present in ALL 21 `electron/src/renderer/src/i18n/locales/*.json` files (the catalog the app loads) with real translations; `tests/test_locale_parity.py` and Electron `locale:check` enforce it. The legacy `electron/src/shared/i18n/` catalog is loaded only by shared-module tests.\n- Docs-sync in the same PR. CHANGELOG Unreleased: quiet one-liners ending `(#N)` + `— thanks @user!` for community work, under a short `**Highlights**` list.\n- Tagged release announcements lead with the biggest user-visible change; redesigns need real UI screenshots and migrations need installer links and steps. Verify all contributor credits from the tag comparison and included PRs; list authors and bug reporters separately (see `docs/RELEASING.md`).\n- Versioning: root `package.json` is the single source of truth; never bump without the owner asking.\n- JavaScript dependency changes require regenerating root `bun.lock` (Docker runs `--frozen-lockfile`).\n- Attribution: commits, PR descriptions and comments carry only the submitter's git identity. Never credit an agent (no agent `Co-authored-by:`, \"Generated with …\", session links) and never add other names/emails. Human co-authors are fine. Enforced by the `commit-identity` check.\n- Issues: absorb or decline — never defer to a future version. Check the open-PR queue before implementing community-reported fixes.\n\n## Shared select controls\n\n- Use `electron/src/shared/components/SearchableSelect.jsx` for all new or redesigned select boxes. Reuse `VoiceSelector` for voice choices. Do not introduce native `<select>` controls.\n- Provide a localized `ariaLabel`; use `menuPortal` inside scrolling or clipping containers. Preserve keyboard selection and disabled states.\n\n## Agent skills\n\nProject development skills are pinned in `skills-lock.json` and installed under\n`.agents/skills/`: Vite and FastAPI.\nRepository rules and tracker mappings override generic skill guidance.\n\n### Issue tracker\n\nGitHub Issues on `debpalash/VoiceStudio`, via the `gh` CLI. See `docs/agents/issue-tracker.md`.\n\n### Triage labels\n\nThe five canonical roles, each label string equal to its name. See `docs/agents/triage-labels.md`.\n\n### Domain docs\n\nSingle-context: `docs/adr/` plus a root `CONTEXT.md` that is created lazily and does not exist yet — skip it when absent. See `docs/agents/domain.md`.\n\n<!-- File: .agents/skills/fastapi-python/SKILL.md (Tokens: ~503 | Category: anthropic-skill) -->\n---\nname: fastapi-python\ndescription: Expert in FastAPI Python development with best practices for APIs and async operations\n---\n\n# FastAPI Python\n\nYou are an expert in FastAPI and Python backend development.\n\n## Key Principles\n\n- Write concise, technical responses with accurate Python examples\n- Favor functional, declarative programming over class-based approaches\n- Prioritize modularization to eliminate code duplication\n- Use descriptive variable names with auxiliary verbs (e.g., `is_active`, `has_permission`)\n- Employ lowercase with underscores for file/directory naming (e.g., `routers/user_routes.py`)\n- Export routes and utilities explicitly\n- Follow the RORO (Receive an Object, Return an Object) pattern\n\n## Python/FastAPI Standards\n\n- Use `def` for pure functions, `async def` for asynchronous operations\n- Use type hints for all function signatures. Prefer Pydantic models over raw dictionaries\n- Structure: exported router, sub-routes, utilities, static content, types (models, schemas)\n- Use ordinary Python control flow; prefer readability over compressed one-line conditionals\n\n## Error Handling\n\n- Handle edge cases at function entry points\n- Employ early returns for error conditions\n- Place happy path logic last\n- Avoid unnecessary else statements; use if-return patterns\n- Implement guard clauses for preconditions\n- Provide proper error logging and user-friendly messaging\n\n## FastAPI-Specific Guidelines\n\n- Use functional components (plain functions) and Pydantic models for input validation\n- Declare routes with clear return type annotations\n- Prefer lifespan context managers for managing startup and shutdown events\n- Leverage middleware for logging, error monitoring, and optimization\n- Use HTTPException for expected errors and model them as specific HTTP responses\n- Apply Pydantic's BaseModel consistently for validation\n\n## Performance Optimization\n\n- Minimize blocking I/O. In `async def` handlers, use awaitable database/API clients; put synchronous SQLite or other blocking work in synchronous routes or explicitly offload it\n- Implement caching with Redis or in-memory stores\n- Optimize Pydantic serialization/deserialization\n- Use lazy loading for large datasets\n\n## Key Conventions\n\n1. Rely on FastAPI's dependency injection system\n2. Prioritize API performance metrics (response time, latency, throughput)\n3. Structure routes and dependencies for readability and maintainability\n\n## Dependencies\n\nFastAPI, Pydantic v2, asyncpg/aiomysql, SQLAlchemy 2.0\n\n<!-- File: .agents/skills/vite/SKILL.md (Tokens: ~1646 | Category: anthropic-skill) -->\n---\nname: vite\ndescription: Expert guidance for Vite development with modern build tooling, HMR, framework integrations, and performance optimization\n---\n\n# Vite Development\n\nYou are an expert in Vite, modern JavaScript/TypeScript build tooling, and frontend development.\n\n## Key Principles\n\n- Leverage native ES modules for fast development\n- Use Vite's opinionated defaults when possible\n- Configure only what needs customization\n- Understand the dev/build differences\n- Optimize for both development speed and production performance\n\n## Project Setup\n\n### Basic Configuration\n```typescript\n// vite.config.ts\nimport { defineConfig } from 'vite';\nimport react from '@vitejs/plugin-react';\n\nexport default defineConfig({\n  plugins: [react()],\n  server: {\n    port: 3000,\n    open: true,\n  },\n  build: {\n    outDir: 'dist',\n    sourcemap: true,\n  },\n});\n```\n\n### Path Aliases\n```typescript\nimport { defineConfig } from 'vite';\n\nexport default defineConfig({\n  resolve: {\n    alias: {\n      '@': new URL('./src', import.meta.url).pathname,\n      '@components': new URL('./src/components', import.meta.url).pathname,\n      '@utils': new URL('./src/utils', import.meta.url).pathname,\n    },\n  },\n});\n```\n\n## Environment Variables\n\n### Usage\n```typescript\n// .env\nVITE_API_URL=https://api.example.com\nVITE_APP_TITLE=My App\n\n// In code\nconst apiUrl = import.meta.env.VITE_API_URL;\nconst isDev = import.meta.env.DEV;\nconst isProd = import.meta.env.PROD;\nconst mode = import.meta.env.MODE;\n```\n\n### Type Definitions\n```typescript\n// src/vite-env.d.ts\n/// <reference types=\"vite/client\" />\n\ninterface ImportMetaEnv {\n  readonly VITE_API_URL: string;\n  readonly VITE_APP_TITLE: string;\n}\n\ninterface ImportMeta {\n  readonly env: ImportMetaEnv;\n}\n```\n\n## Hot Module Replacement\n\n### Manual HMR\n```typescript\n// For libraries without HMR support\nif (import.meta.hot) {\n  import.meta.hot.accept('./module.ts', (newModule) => {\n    // Handle the updated module\n    console.log('Module updated:', newModule);\n  });\n\n  import.meta.hot.dispose(() => {\n    // Cleanup before module is replaced\n  });\n}\n```\n\n## Asset Handling\n\n### Static Assets\n```typescript\n// Import as URL\nimport imageUrl from './image.png';\n// <img src={imageUrl} />\n\n// Import as string (raw)\nimport shaderCode from './shader.glsl?raw';\n\n// Import as worker\nimport Worker from './worker.ts?worker';\nconst worker = new Worker();\n```\n\n### Public Directory\n```\npublic/\n├── favicon.ico      # Served at /favicon.ico\n├── robots.txt       # Served at /robots.txt\n└── images/          # Served at /images/\n```\n\n## Framework Integrations\n\n### React\n```typescript\nimport { defineConfig } from 'vite';\nimport react from '@vitejs/plugin-react';\n\nexport default defineConfig({\n  plugins: [\n    react({\n      // Babel plugins\n      babel: {\n        plugins: ['@emotion/babel-plugin'],\n      },\n    }),\n  ],\n});\n```\n\n### Vue\n```typescript\nimport { defineConfig } from 'vite';\nimport vue from '@vitejs/plugin-vue';\n\nexport default defineConfig({\n  plugins: [vue()],\n});\n```\n\n### Svelte\n```typescript\nimport { defineConfig } from 'vite';\nimport { svelte } from '@sveltejs/vite-plugin-svelte';\n\nexport default defineConfig({\n  plugins: [svelte()],\n});\n```\n\n## Build Optimization\n\n### Code Splitting\n```typescript\n// Dynamic imports create separate chunks\nconst AdminPanel = lazy(() => import('./AdminPanel'));\n\n// Manual chunks\nexport default defineConfig({\n  build: {\n    rollupOptions: {\n      output: {\n        manualChunks: {\n          vendor: ['react', 'react-dom'],\n          utils: ['lodash', 'date-fns'],\n        },\n      },\n    },\n  },\n});\n```\n\n### Chunk Size Optimization\n```typescript\nexport default defineConfig({\n  build: {\n    chunkSizeWarningLimit: 500,\n    rollupOptions: {\n      output: {\n        manualChunks(id) {\n          if (id.includes('node_modules')) {\n            return id.split('node_modules/')[1].split('/')[0];\n          }\n        },\n      },\n    },\n  },\n});\n```\n\n## CSS Handling\n\n### CSS Modules\n```typescript\n// styles.module.css is auto-detected\nimport styles from './styles.module.css';\n\n// <div className={styles.container}>\n```\n\n### PostCSS\n```javascript\n// postcss.config.js\nexport default {\n  plugins: {\n    tailwindcss: {},\n    autoprefixer: {},\n  },\n};\n```\n\n### Preprocessors\n```typescript\n// Automatically handled with package installed\n// npm install -D sass\nimport './styles.scss';\n```\n\n## Proxy Configuration\n\n```typescript\nexport default defineConfig({\n  server: {\n    proxy: {\n      '/api': {\n        target: 'http://localhost:4000',\n        changeOrigin: true,\n        rewrite: (path) => path.replace(/^\\/api/, ''),\n      },\n      '/socket.io': {\n        target: 'ws://localhost:4000',\n        ws: true,\n      },\n    },\n  },\n});\n```\n\n## Plugin Development\n\n```typescript\n// my-vite-plugin.ts\nimport type { Plugin } from 'vite';\n\nexport function myPlugin(): Plugin {\n  return {\n    name: 'my-plugin',\n\n    // Hook: modify config\n    config(config, { mode }) {\n      return {\n        define: {\n          __BUILD_TIME__: JSON.stringify(new Date().toISOString()),\n        },\n      };\n    },\n\n    // Hook: transform code\n    transform(code, id) {\n      if (id.endsWith('.md')) {\n        return {\n          code: `export default ${JSON.stringify(code)}`,\n          map: null,\n        };\n      }\n    },\n\n    // Hook: configure dev server\n    configureServer(server) {\n      server.middlewares.use((req, res, next) => {\n        // Custom middleware\n        next();\n      });\n    },\n  };\n}\n```\n\n## Testing with Vitest\n\n```typescript\n// vitest.config.ts\nimport { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  test: {\n    globals: true,\n    environment: 'jsdom',\n    setupFiles: './src/test/setup.ts',\n    coverage: {\n      provider: 'v8',\n      reporter: ['text', 'json', 'html'],\n    },\n  },\n});\n```\n\n## SSR Configuration\n\n```typescript\nexport default defineConfig({\n  build: {\n    ssr: true,\n    rollupOptions: {\n      input: './src/entry-server.ts',\n    },\n  },\n  ssr: {\n    external: ['express'],\n    noExternal: ['my-ui-library'],\n  },\n});\n```\n\n## Library Mode\n\n```typescript\nexport default defineConfig({\n  build: {\n    lib: {\n      entry: './src/index.ts',\n      name: 'MyLib',\n      fileName: (format) => `my-lib.${format}.js`,\n    },\n    rollupOptions: {\n      external: ['react', 'react-dom'],\n      output: {\n        globals: {\n          react: 'React',\n          'react-dom': 'ReactDOM',\n        },\n      },\n    },\n  },\n});\n```\n\n## Best Practices\n\n- Use `vite preview` to test production builds locally\n- Keep dependencies that support ESM in regular deps\n- Use `optimizeDeps.include` for CommonJS dependencies\n- Enable `build.sourcemap` for debugging production\n- Use `server.warmup` for faster dev server starts\n\n<!-- File: .claude/skills/omnivoice/LEGACY.md (Tokens: ~328 | Category: anthropic-skill) -->\n# VoiceStudio compatibility entry\n\nThe current cross-agent package is [voicestudio](../../../../skills/voicestudio/SKILL.md).\nFor new installations use `npx skills add debpalash/VoiceStudio --skill voicestudio`.\n\nUse the running backend at the user's configured address (default\n`http://localhost:3900`). Check `/health`, discover `/openapi.json` and\n`/v1/audio/voices`, then use the installed schema for speech, transcription,\nprofiles, and jobs. The HTTP MCP endpoint is `/mcp`; discover tools from the\nconnected server instead of assuming this older package's tool inventory.\n\nLaunch the installed Electron app if the backend is unavailable. For source\ndevelopment follow the checkout's Electron README. Existing helpers in\n`scripts/` support legacy source installations; inspect their environment\nand dependency assumptions before running them.\n\nModel downloads and remote services require the user's choice. Never silently\ninstall models, promise fixed latency, or treat compatibility voice names as\nreal provider voices. Validate saved audio and asynchronous job completion\nbefore reporting success. Protected backends require configured credentials;\nnever disable authentication to make an example work.\n\nSource and current setup documentation:\nhttps://github.com/debpalash/VoiceStudio\n\nThis archived entry is not an installable skill. Existing installations should\nremove the old `omnivoice` / `oss-maintainer` entries and install `voicestudio` /\n`voicestudio-maintainer` from the canonical repository. Legacy helpers remain\nfor existing users; the Electron supervisor is the preferred launcher.\n\n<!-- File: .claude/skills/omnivoice/references/engines-comparison.md (Tokens: ~300 | Category: anthropic-skill) -->\n# References Skill\n\nPath: `.claude/skills/omnivoice/references/engines-comparison.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/references/engines-comparison.md)\n\n<!-- File: .claude/skills/omnivoice/references/mcp-setup.md (Tokens: ~300 | Category: anthropic-skill) -->\n# References Skill\n\nPath: `.claude/skills/omnivoice/references/mcp-setup.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/references/mcp-setup.md)\n\n<!-- File: skills/voicestudio-maintainer/SKILL.md (Tokens: ~1144 | Category: anthropic-skill) -->\n---\nname: voicestudio-maintainer\ndescription: Triage GitHub issues, review contributor pull requests, diagnose CI, and prepare explicitly requested releases for VoiceStudio's Electron desktop app and Python backend. Use for repository maintenance work, not ordinary VoiceStudio audio generation.\n---\n\n# VoiceStudio maintenance\n\nRead the target repository's AGENTS.md, CLAUDE.md, contribution guide, and release documentation first. Their policies override this general workflow. Installing this skill does not authorize merges, releases, issue closures, or messages to contributors.\n\n## Triage and implementation\n\n- Inspect current code and existing PRs before duplicating a reported fix. Reuse contributor work where it solves the problem; retain attribution.\n- Reproduce the reported behavior where possible. Separate confirmed failures from diagnosis, and record meaningful limitations in the PR.\n- Fix the cause with the smallest complete change. Test observable behavior where it can regress; do not mistake a source-text assertion for an end-to-end test.\n- Preserve local changes. Use an isolated worktree when branch switching would disturb them.\n- Read existing CI failures and reviewer comments before rerunning work. Diagnose failures before retries; never hide a failing gate behind a successful piped command.\n- Keep user-facing docs and required translations aligned with the implementation.\n\n## Review and authorized landing\n\nReview the current diff, bot findings, and required checks against current main. Resolve material findings on the PR branch before landing; do not merge first and promise a follow-up. Refresh stale branches using the repository's policy and preserve contributor commits.\n\nBefore an authorized merge, verify required checks are green, the head has not changed, and the PR is mergeable. After landing, inspect main's own runs; investigate regressions immediately. Report remaining blockers without inventing a successful verification.\n\n## Release preparation\n\nPreparing CI or packaging is distinct from publishing. Do not tag, bump versions, enable publishing, or cut a release unless that action is authorized.\n\nUse the repository's version source of truth, changelog format, supported platforms, and distribution channels. Validate packaging and workflows without publishing when that is the requested scope. After an authorized release, verify actual artifacts, release notes, updater metadata, and requested registry channels; a green build alone does not prove distribution.\n\n## Communication\n\nLead with the outcome and evidence. Credit concrete contributor work. Do not close stale issues merely because of age, or claim reporter confirmation that has not occurred. For authorized closures, give the resolution and what evidence would justify reopening.\n\n## VoiceStudio-specific routing\n\nWhen maintaining debpalash/VoiceStudio, consult its current rules rather than old architecture assumptions:\n- Electron development and packaging: `electron/README.md`, `electron/package.json`, and `.github/workflows/`.\n- Backend contracts: running `/openapi.json`, `backend/api/`, and targeted tests.\n- Release channels and version ownership: `docs/RELEASING.md` and CLAUDE.md. Never infer a version bump from a fix request.\n- Read CodeRabbit/Greptile findings and required CI before merging. Follow main's post-merge CI.\n- Preserve local-first behavior, cross-platform behavior, model-install consent, synthetic-audio marking, and localization requirements.\n\n## Current development commands\n\nRun from the repository root:\n\n```sh\nbun install\nbun run setup:api        # prepare the source Python runtime explicitly\nbun run dev              # Electron + supervised backend\nbun run typecheck        # Electron main, preload, and renderer\nbun run test             # Electron tests\nbun run check:electron   # types, tests, build, packaging contract\nbun run dist             # local installers; publishing disabled\n```\n\n`electron/src/main/` owns lifecycle, IPC, native helpers, and backend supervision;\n`electron/src/preload/` exposes the renderer bridge; `electron/src/renderer/src/`\ncontains the React app. Keep privileged filesystem/process work out of the renderer.\n`electron/src/shared/` holds modules shared with the browser build; it is not a\nrunnable app. `backend/` supplies the shared Python API; `native/desktop-bridge/`\nsupplies native capabilities. `frontend/` only receives the browser build output\n(`bun run build:web` → `frontend/dist/`, served by the backend in Docker). Do not\nrename internal `omnivoice` packages, environment keys, or data paths as a\nbranding cleanup.\n\nElectron is the only desktop app and web UI. The Tauri shell is removed; do not\nrestore it. Its final v0.5.3 updater feeds are immutable compatibility assets,\nand old Tauri installs move over with `docs/electron-migration.md`.\nUse `electron-build.yml` for artifact-only packaging rehearsals; inspect its\nresults for Windows x64, Linux, macOS Intel, and macOS Apple Silicon (Windows\nARM64 is an experimental leg that may fail without blocking).\nDo not dispatch release/publishing workflows to test packaging. Signing, updater\nmigration, and successful installation are separate checks from a green build.\nThe app version comes from the root `package.json` (mirrored in `pyproject.toml`\nand `backend/core/version.py`); do not bump it without an explicit versioning task.\n\nFor backend tests, use the repo's CI dependencies and an empty temporary\n`HF_HUB_CACHE` with `HF_HUB_OFFLINE=1`; installed developer models must not hide\nmissing fixtures. Run targeted tests while editing and the required full checks\nbefore landing. Existing CI failures remain blockers, not implied waivers.\n\n<!-- File: skills/voicestudio/SKILL.md (Tokens: ~1282 | Category: anthropic-skill) -->\n---\nname: voicestudio\ndescription: Generate local speech with saved or designed voices, transcribe audio, and automate dubbing or narration workflows through VoiceStudio's REST API or MCP server. Use when the user wants to work with VoiceStudio audio or connect it to an agent or automation.\n---\n\n# VoiceStudio\n\nUse the user's running [VoiceStudio](https://github.com/debpalash/VoiceStudio) backend. Prefer local processing; cloud translation, model downloads, remote-backend connections, and external integrations require the user's choice. Installed models can run offline; do not promise that every configured workflow is offline.\n\n## Connect and discover\n\nThe default backend is `http://localhost:3900`; honor the user's configured address. Electron's renderer and development proxy are separate services, not the public backend API.\n\n1. Check `GET /health`.\n2. Discover the running version's contracts with `GET /openapi.json`, and voices/engines with `GET /v1/audio/voices`. Do not invent profile IDs or infer installed models from a catalog listing.\n3. If unavailable, launch the installed app. For an existing source checkout, follow its Electron README (`bun install`, `bun run setup:api`, then `bun run dev` from the repository root). Do not install a second backend or overwrite an existing checkout.\n4. Local configurations may permit unauthenticated calls; protected deployments require the configured credentials. Treat 401/403 as authentication failures, not permission to disable auth. Never print tokens or use a placeholder key as if it were a real credential.\n\n## Generate speech\n\nSave this JSON to `speech-request.json`, replacing `voice` with a discovered profile ID when the user selected a voice:\n\n```json\n{\"model\":\"tts-1\",\"voice\":\"alloy\",\"input\":\"Every voice has a story. Let's tell yours.\",\"response_format\":\"wav\"}\n```\n\n```sh\ncurl --fail-with-body --show-error http://localhost:3900/v1/audio/speech \\\n  -H 'Content-Type: application/json' --data-binary @speech-request.json \\\n  --output speech.wav\n```\n\n`tts-1` and `tts-1-hd` are aliases, not quality guarantees. OpenAI voice names are compatibility aliases, not those providers' actual voices. Prefer a discovered saved voice for repeatable narration. Check the installed engine's language and voice-design capabilities before promising a result.\n\nCheck the HTTP status and decode/probe the output before calling it audio: an error response can be written to the output path. Report the saved path and actual duration/format. Never fabricate a successful generation, transcript, or job completion.\n\n## Transcribe\n\n```sh\ncurl --fail-with-body --show-error http://localhost:3900/v1/audio/transcriptions \\\n  -F file=@clip.wav -F model=whisper-1 -F response_format=verbose_json\n```\n\nUse `json` or `text` for plain transcripts, `verbose_json` for timestamps, and `srt`/`vtt` for subtitles when supported by the running schema. Check transcription-model readiness before long recordings; explain a missing model and obtain download authorization rather than silently installing it.\n\n## Cloning, design, dubbing, and longer workflows\n\nUse the installed OpenAPI schema to discover profile creation, reference uploads, generation, dubbing, and long-form job operations. Their native endpoints are broader than the OpenAI compatibility API and evolve independently.\n\n- Clone only voices the user is authorized to use. Preserve reference files and existing profiles.\n- For design, capture the requested tone, delivery, language, and sample text; check engine support.\n- For dubbing, retain original media, speaker assignments, segment timing, and background-audio intent. Translation completion is not rendered-dub completion.\n- For asynchronous work, use returned job IDs and documented progress/status endpoints. Inspect terminal errors; avoid blindly resubmitting timed-out generation.\n- Return usable files and honest limitations, including missing models or unavailable capabilities.\n\n## MCP and automation\n\nThe running backend mounts an MCP endpoint at `http://localhost:3900/mcp`. Use the client's supported HTTP transport and discover its tools at runtime. Reuse an existing connection rather than spawning another service. For stdio-only clients, consult the project's [MCP guide](https://github.com/debpalash/VoiceStudio/blob/main/docs/mcp.md) for its shim.\n\nFor n8n, calling agents, containers, or other hosts, make the backend address reachable from that environment: container `localhost` refers to the container. Keep authentication and explicit remote-routing choices intact. An integration-directory listing does not mean the integration is connected.\n\nOn errors, read the response body, distinguish unavailable backend, missing model, unsupported capability, authentication, and busy hardware. Fix the reported condition; do not switch to a hosted provider or download a model without authorization.\n\n## Desktop workflows and readiness\n\nThe Electron app includes voice cloning and design, saved profiles and gallery,\nstories/audiobooks, dubbing projects, transcription, tools, and integrations.\nPrefer its existing project and voice identifiers over creating duplicates.\nFor desktop automation, inspect the actual UI and current Settings shortcuts;\ndo not assume shortcut bindings or microphone permissions are the same on every host.\n\nBefore dictation, verify an installed speech-to-text model and a working input\ndevice. Distinguish recording, paused recording, transcription processing, and\ncompleted text. Copying a transcript and inserting it into another app are different\noperations; confirm the intended target before typing and preserve clipboard content\nwhere supported. Never report text delivered just because transcription completed.\n\nFor dubbing, inspect missing/failed segments and timing overflow before export.\nPreserve music and non-speech audio when requested; do not silently replace the\nwhole soundtrack. Preserve the source and make the output a separate artifact.\nTranslation style prompts belong to the selected translation operation, and remote\nagent translation requires the user's configured provider choice.\n\nUse the integrations directory as discovery and setup guidance, not proof of a\nworking connector. Verify actual credentials, endpoint reachability, and supported\noperations before describing a connection as ready. Container deployments need\npersistent data volumes and a backend URL reachable by the calling client.\n\n<!-- File: tests/evals/suites/dub_translation_naturalness.yaml (Tokens: ~300 | Category: anthropic-skill) -->\n# Suites Skill\n\nPath: `tests/evals/suites/dub_translation_naturalness.yaml`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/tests/evals/suites/dub_translation_naturalness.yaml)\n\n<!-- File: .claude/skills/omnivoice/scripts/check-health.sh (Tokens: ~300 | Category: claude-rule) -->\n# Claude Directive: check-health.sh\n\nPath: `.claude/skills/omnivoice/scripts/check-health.sh`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/scripts/check-health.sh)\n\n<!-- File: .claude/skills/omnivoice/scripts/record-reference.sh (Tokens: ~300 | Category: claude-rule) -->\n# Claude Directive: record-reference.sh\n\nPath: `.claude/skills/omnivoice/scripts/record-reference.sh`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/scripts/record-reference.sh)\n\n<!-- File: .claude/skills/omnivoice/scripts/start-backend.sh (Tokens: ~300 | Category: claude-rule) -->\n# Claude Directive: start-backend.sh\n\nPath: `.claude/skills/omnivoice/scripts/start-backend.sh`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/scripts/start-backend.sh)\n\n<!-- File: .claude/skills/omnivoice/scripts/stop-backend.sh (Tokens: ~300 | Category: claude-rule) -->\n# Claude Directive: stop-backend.sh\n\nPath: `.claude/skills/omnivoice/scripts/stop-backend.sh`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/debpalash/OmniVoice-Studio/HEAD/.claude/skills/omnivoice/scripts/stop-backend.sh)\n\n<!-- File: CLAUDE.md (Tokens: ~4997 | Category: claude-rule) -->\n## Active desktop: Electron only\n\nElectron (`electron/`) is the only desktop and web UI. The Tauri shell and legacy\nUI entrypoints are removed; do not restore build, runtime, release, or CI paths for\nthem. Triage reports from final Tauri installations toward the migration guide and\npreserve their immutable updater feeds. Some modules under `electron/src/shared/` remain\ntemporarily shared by Electron; they are not a runnable app. New UI, IPC, setup\ninstructions, tests, and browser assets belong in Electron; validate Electron on\nmacOS, Windows and Linux.\n\n## Mobile: native iOS and Android (owner-set 2026-10-17)\n\n`mobile/ios/` (Swift/SwiftUI) and `mobile/android/` (Kotlin/Compose) are native\napps that run models **on the phone** (TTS, dictation, voice cloning, dub\ntranslation; owner-set 2026-10-18) and can also drive a user's own VoiceStudio\ncomputer. Phone first: once models are downloaded they work offline with no\ncomputer; pairing adds the heavy engines, chosen per task. The companion-only\nbuild is the base, not the product. They implement one shared contract,\n`mobile/contract/SPEC.md`: a mobile feature ships on both or neither.\nTheme, API and strings are generated, never hand-copied: `bun\nscripts/export-mobile-tokens.ts` (from the Electron theme), `uv run python\nscripts/export_openapi.py` (from the backend) and the Electron locale catalogs;\n`tests/test_mobile_contract.py` fails on drift. Desktop/web UI still belongs in\nElectron only.\n\n<!-- GSD:project-start source:PROJECT.md -->\n## Project\n\n**VoiceStudio**\n\nVoiceStudio is an open-source, fully-local ElevenLabs alternative — a desktop app for voice cloning, voice design, video dubbing, and real-time dictation across 646 languages. It runs entirely on the user's machine (CUDA/MPS/ROCm/CPU auto-detect), with no API keys, no accounts, and no cloud dependencies. It's an active beta with a growing user base who hit it with real workloads (50-video batches, multi-engine setups, edge-OS platforms) and report friction in GitHub Issues and Discord. The current version lives in the root `package.json` (the single source of truth — see Versioning); the latest stable tag is on the [Releases page](https://github.com/debpalash/VoiceStudio/releases/latest). With `AUTO_VERSION_BUMP` off (the current owner setting), `main` holds at the released version between releases.\n\n**Core Value:** **A first-run that actually works.** A user who downloads the installer (or clones the repo) should reach a working voice-cloning or dubbing output without hitting a wall — and when something does go wrong, the error or docs should tell them exactly what to do.\n\nEverything else (new engines, fancy features) is downstream of \"the thing installs and runs reliably across platforms, with the engines and pipelines users already depend on staying compatible.\"\n\n### Constraints\n\n- **Existing engine compatibility**: Users with already-installed engines (IndexTTS, CosyVoice, etc.) must not have to reinstall. Fixes touching engine code must be backward-compatible with on-disk model state.\n- **Cross-platform parity**: Every fix must work on macOS (Apple Silicon; Intel Macs are limited to the app UI with a remote backend, as README.md and `docs/install/macos.md` document), Windows (x64), and Linux (AppImage + deb). No platform-only regressions; the cross-platform bug bash (PR #51) is the baseline.\n- **Default features must work on every platform (strict rule, 2026-05-20):** A feature that ships in default mode — out-of-the-box, no user customization, no opt-in toggle — must behave identically on macOS, Windows, and Linux. Platform-specific *implementation code* is allowed for OS APIs / shells / packaging, but the user-visible *default behavior* cannot diverge. Platform-only features (e.g., a macOS-only global shortcut, a Windows-only path picker) must go behind explicit user opt-in: Settings toggle, env var, or CLI flag. When a default doesn't work on a platform, that's a P0 bug — either fix it on the missing platform or move it behind opt-in. No third option. **This rule governs BEHAVIOUR, not PERFORMANCE** (clarified 2026-07-30, council): hardware acceleration is expected to vary by host — CUDA, MPS, DirectML, Triton availability and `torch.compile` are all host-dependent by design, and reading the rule to forbid that would forbid GPU support itself. An optimization that is skipped where it cannot work (missing Triton, an arch the wheel lacks, a path its toolchain cannot link) is NOT a parity violation; a *feature* the user can see and use on one OS but not another is.\n- **Backward-compatible project data**: Existing `omnivoice_data/` (user voices, projects, settings) must keep working without manual migration. Any DB schema change goes through alembic with a tested upgrade path.\n- **Local-first guarantee preserved**: nothing leaves the machine without the user's **explicit yes**, and the app must remain fully functional with everything declined. Auto bug reporting is opt-in and submits only to GitHub Issues (prefilled-URL, from the user's own browser). Product analytics (owner-sanctioned 2026-07-16; US project migration 2026-09-26) is opt-in PostHog US with a **first-run consent prompt** — two equal-weight Yes/No buttons, never default-on, skipping = off; consent-gated, allowlisted content-free metadata only (`backend/core/analytics.py`); every build — installer, Docker, and source alike (owner reversal 2026-07-20, #1193) — carries the in-repo publishable write-only token and shows the same consent ask, with env/baked token overriding it. No required cloud calls, accounts, or API keys. Sanctioned calls (owner-set 2026-10-02; full list in `.github/CONTRIBUTING.md` → Quality gates): during first-run setup the user starts — the pinned ffmpeg download from GitHub `zackees/ffmpeg_bins` (`backend/services/media_tools.py`), the huggingface.co/hf-mirror.com reachability probe for restricted networks (`backend/services/endpoint_race.py`), and Hugging Face model downloads; opening the community gallery (jsDelivr manifest, `backend/api/routers/community.py`) or enabling the voice-preview gallery (GitHub Releases, `backend/services/gallery.py`); packaged update checks against GitHub Releases (`electron/src/main/updater.ts`); yt-dlp updates from PyPI when the user clicks update; and, only after the user turns account features on (first-run setup or Settings → Account, off by default), VoiceStudio Cloud sign-in and account calls from Electron main (`electron/src/main/account/`), plus settings sync from the backend (`backend/services/cloud_sync/`) once cloud sync is also on, all stopped at once when switched off. Narrow owner-approved exception (2026-09-28): the GitHub Star badge may fetch the public repository star count when shown and refresh every 20 minutes while visible, without credentials or a referrer. It sends no project, recording, or account data, retains the last count on failure, and never blocks offline use.\n- **Beta release cadence (no RC, no ceremony — strict rule, 2026-05-20):** the current release line (0.5.x today) has **no release candidates, no 48h soak, no formal release ceremony**. Every fix goes continuous-to-main; the owner tags a patch from main whenever the current state is worth cutting. No `-rc` tags. No phased release. The one sanctioned prerelease is the opt-in **Beta channel** (owner-approved 2026-10-22): `vX.Y.Z-beta.N` tags cut from `main`, published as GitHub prereleases that never become `latest`, with their own `electron-beta-*` update feed and `:beta` Docker tag (see `docs/RELEASING.md` → Beta channel). It adds no soak, ceremony or side branch. No deferrals to a future minor or major version — every open issue and every open community PR gets absorbed into the current line or explicitly declined. Users follow `main` for previews; users wanting stable stay on the latest tagged release.\n<!-- GSD:project-end -->\n\n<!-- GSD:stack-start source:research/STACK.md -->\n## Technology Stack\n\nThe May-2026 stack research that used to live here served five capabilities that have all since shipped (HF-token Settings panel, prefilled-URL bug reporting, uv mirror fallback for restricted networks, the Supertonic-3 engine, in-repo Markdown docs). Follow the patterns in the code itself; the durable *don'ts* that research established:\n\n- **No third-party endpoints for bug reporting or crash dumps** (`sentry-tauri` was evaluated and rejected) — bug reporting stays opt-in via prefilled GitHub-issue URLs, submitted from the user's own browser. The one sanctioned third-party endpoint is the opt-in PostHog US product analytics and error tracking (owner-set 2026-07-16; migrated 2026-09-26; sanitized renderer errors approved 2026-09-26), which is consent-gated behind the first-run prompt and ships allowlisted content-free metadata only. Raw exception, DOM, and session autocapture stay disabled; manually captured renderer exceptions must replace messages and scrub stack paths before transmission. Its publishable write-only project token is committed in-repo (owner reversal 2026-07-20, #1193 — source builds get the same consent-gated analytics as installers; env/baked token overrides), allowed by `tests/test_no_committed_analytics_token.py` in exactly `backend/core/analytics.py` + `electron/src/shared/utils/analytics.ts`.\n- **No PAT/token-based GitHub posting from the app** — the user submits from their own browser.\n- **Don't recommend `setx` for env vars on Windows** (silent truncation, no current-shell propagation) — use the in-app Settings panel or PowerShell `[Environment]::SetEnvironmentVariable`.\n- **Don't adopt Material for MkDocs** for any future docs site (maintenance mode since Nov 2025) — Astro Starlight is the precedent if docs ever outgrow the repo.\n- **`hf_transfer` is deprecated** — default `huggingface_hub` (hf-xet) handles downloads.\n\nFor anything new: prefer what's already pinned in `pyproject.toml` / `electron/package.json`, and check `uv tree` for conflicts before adding a dependency.\n<!-- GSD:stack-end -->\n\n<!-- GSD:conventions-start source:CONVENTIONS.md -->\n## Conventions\n\n**Versioning (hard rule, owner-set 2026-06-11; single-source 2026-09-26):** **The root `package.json` is the SINGLE SOURCE OF TRUTH for the maintained Electron app version** — Electron's builder reads it directly and Vite injects `__APP_VERSION__` for the UI and bug reports. Two toolchain-required **mirrors** are kept equal to it and bumped in lockstep: `pyproject.toml` and `backend/core/version.py`'s `_FALLBACK_VERSION`. Guarded by `tests/test_app_version.py`. Version bumps are manual and happen only when the owner asks; until then, `main` may equal the latest released version. Consequences:\n- Every PR and preview build uses the canonical version. Preview artifacts add the workflow run number without changing the checked-in version.\n- Releasing = obtain owner approval for the version, bump the canonical version and maintained mirrors together, then tag that exact version from `main` after validation.\n- Docker: `ghcr.io/debpalash/voicestudio:latest` = **main** (rolling preview); `:X.Y.Z` + `:X.Y` + `:stable` = tagged releases; `:beta` + `:X.Y.Z-beta.N` = beta prereleases (never `:stable`/`:X.Y`). `:latest` is the preview channel by design — stable users pin `:stable` or a version tag. The former `ghcr.io/debpalash/omnivoice-studio` coordinate remains a compatibility alias.\n- Do not bump minor/major or invent RCs/codenames without the owner asking. A beta version (`X.Y.Z-beta.N`) is bumped in the same three places, only when the owner asks, and uses the same lockstep. No \"defer to next version\" labels — scope is absorbed or declined, never re-versioned.\n\n**Docs-sync (hard rule, owner-set 2026-06-11):** any change that alters something these docs describe — README.md, `.github/CONTRIBUTING.md`, `.github/SECURITY.md`, `.github/SUPPORT.md`, LICENSE, or `docs/**` (install flows, Docker tag semantics, platform support, versioning/release behavior, review process, supported versions) — must update those docs **in the same PR** as the change. If a doc impact is discovered after merge, the docs fix is the immediate next commit, not backlog. Stale docs are treated as bugs.\n\n**Release notes / changelog (hard rule, owner-set 2026-06-16):** every tagged release gets a **high-quality, user-facing `## [X.Y.Z] — DATE` section in `CHANGELOG.md`** before (or in the same hour as) the tag — never the \"Auto-generated release for vX.Y.Z…\" fallback. The desktop release workflow extracts that section verbatim as the GitHub Release body, so a missing/empty section ships a bare release. Quality bar (owner-restyled 2026-07-17, replaces the old bold-lead paragraphs): **quiet and scannable change entries** — after an optional tagged-release introduction (see the presentation rule below), a short `**Highlights**` bullet list (plain words, one line each), then `### Changed` / `### Added` / `### Docs` / `### Fixed` / `### License` / `### CI` subsections where each entry is a **single one-liner** with the `(#NNN)` issue/PR ref and contributor credit (`— thanks @user!`) where applicable. Change entries are written for users, grouped by theme, with no multi-line entry paragraphs or raw commit dumps. This applies to **preview builds too**: preview release notes summarize what's new on `main` since the last stable, in the same style. Workflow: as features merge, keep `## [Unreleased]` current; at release time rename it to the version + date. If a release was already cut with the fallback body, the next action is to backfill `CHANGELOG.md` **and** `gh release edit <tag>` the live body — not backlog.\n\n**Release presentation and credits (owner-set 2026-09-17):** Tagged release announcements lead with the biggest user-visible change; redesigns need real UI screenshots and migrations need installer links and steps. Verify all contributor credits from the tag comparison and included PRs; list authors and bug reporters separately (see `docs/RELEASING.md`). Keep Highlights to 3–5 bullets; the release introduction can include prose, images, and a download table before the concise change entries.\n\n**Localization (hard rule):** No hardcoded non-English (CJK) **user-facing text** anywhere in the codebase except the translation layers: `electron/src/renderer/src/i18n/` (the catalog the app loads; checked by `tests/test_locale_parity.py` and Electron `locale:check`) and the legacy `electron/src/shared/i18n/` (loaded only by shared-module tests). All UI strings go through i18n (`t('...')` keys in `locales/*.json`); native language names live in `i18n/index.ts` (`LANGUAGES`). Functional CJK is allowed and tracked via the allowlist in `tests/test_no_hardcoded_cjk.py` — text-processing regexes, model/engine vocabulary & identifiers (e.g. CosyVoice speaker IDs), localized error matching, demo/eval data, and test fixtures. CI fails on any hardcoded CJK outside the allowlist; to add legitimate functional CJK, extend `_ALLOWED_FILES` there with a justification.\n\n**Release deployment channels (hard rule, owner-set 2026-07-16):** a version bump is not \"released\" until **every** maintained channel ships it — the full checklist lives in `docs/RELEASING.md`. The channels are the Electron GitHub Release (Linux x64, Windows x64 + experimental ARM64, macOS arm64 + x64), GHCR and Docker Hub in CUDA and ROCm flavors, and the Docker Hub overview page synced from `deploy/dockerhub-overview.md`. The final Tauri feeds are immutable compatibility assets copied into releases for old clients; they are never rebuilt. Verify all channels after tagging. Preview/RC builds always source from `main`; never cut a side-branch build.\n\n**Fix quality (hard rule, owner-set 2026-06-16):** Fix issues *properly* and future-maintenance-proof — don't stop at the symptom. Root-cause fully, fix the whole **class** of the bug (not just the one reported instance), add a fail-before/pass-after regression test, and harden against recurrence (e.g. if a lockfile drift only fails in Docker, also make CI catch it). Go the extra mile where it durably pays off. Be token-efficient about it — extra **effort**, not extra **verbosity**: no padding, no redundant re-checks, the smallest correct change that is also recurrence-proof. Don't be shy to spend the effort a proper fix needs; do be shy about wasting tokens.\n\n**Keep main green (hard rule, owner-set 2026-06-16):** A merge must **never break `main`'s CI**. Before a change lands, verify the *full* active CI matrix and `deploy/Dockerfile`, not only the checks you happened to run. Dependency / lockfile / config changes must be validated against all maintained consumers. The lockfile is the repo-root `bun.lock`; any workspace package change requires regenerating it and confirming `bun install --frozen-lockfile` passes. Re-check CodeQL/Security on code changes and the Electron native helper on Rust changes. Do not use the archived Tauri build as a gate.\n\nOther conventions not yet established. Will populate as patterns emerge during development.\n**Attribution and identity (hard rule, owner-set 2026-10-02):** commits, PR descriptions, and issue/PR comments carry only the submitter's own git identity. AI agents are never credited: no agent `Co-authored-by:` trailer, no \"Generated with …\" line, no session links, no agent author/committer. Never put names or emails other than the configured git identity into commits or comments (no personal emails, no placeholder identities). Human co-authors are fine. Enforced on PRs by `scripts/check_commit_identities.py` (the `commit-identity` check).\n\n<!-- GSD:conventions-end -->\n\n<!-- GSD:architecture-start source:ARCHITECTURE.md -->\n## Architecture\n\nArchitecture not yet mapped. Follow existing patterns found in the codebase.\n<!-- GSD:architecture-end -->\n\n<!-- GSD:skills-start source:skills/ -->\n## Project Skills\n\n- `vite` — Vite configuration, assets, HMR, builds, and Vitest guidance.\n- `fastapi-python` — FastAPI and Pydantic implementation patterns.\n\nCanonical copies live under `.agents/skills/`; `skills-lock.json` pins their sources and hashes. Claude should follow these paths directly, avoiding cross-platform symlinks.\n<!-- GSD:skills-end -->\n\n<!-- GSD:workflow-start source:GSD defaults -->\n## Workflow\n\nDirect repo edits are authorized (owner decision, 2026-07-08). The GSD command gate that used to live here referenced `/gsd-quick` / `/gsd-debug` / `/gsd-execute-phase` skills that are not installed in this environment; the owner chose to keep working directly rather than restore them. The working conventions that matter are in **Conventions** above — versioning, docs-sync, changelog, localization, fix quality, keep-main-green — plus: gate every merge on the \"Tests (backend + frontend)\" check passing and the PR being MERGEABLE, and check the open-PR queue before implementing any community-reported fix (contributors may have already submitted one).\n\n**Harvest bot reviews before merging (rule, 2026-07-20):** CodeRabbit and Greptile auto-review every PR (tuned via `.coderabbit.yaml` / `greptile.json`, both fed CLAUDE.md as context). Before merging ANY PR — including your own — read their inline comments (`gh api repos/<owner>/<repo>/pulls/<N>/comments` filtered by bot login) and triage: fix real findings, ignore noise, never merge with an unread Critical/P1. They are the free first review pass; reserve deep agent-driven review for what they can't judge (architecture, cross-file semantics, product intent). Mechanical rules belong in deterministic CI tests, not in any AI reviewer.\n\n**Token economy (owner directive, 2026-07-20; tightened 2026-07-28):** default to the shortest response that fully answers — outlines and tables over prose, no preamble, no recap of work just done, no re-explaining what the diff shows; applies to every response, not just status updates. Lead with the outcome; one-line statuses; no narration, filler, or diff-restating. Read what CI/linters/review bots already computed instead of re-deriving it. Mechanical rules belong in deterministic tests (changelog style, locale parity, version lockstep, CJK — all in `tests/`), never in agent effort. Targeted tests while iterating; full suites only before landing. `AGENTS.md` carries this contract for all agents — keep the two in sync.\n\n**Never accept a PR as-is (owner directive, 2026-07-20):** review findings — bot, agent, or human — get FIXED on the PR branch before merge (maintainer commits are fine and credit the contributor in the changelog); do not merge with known issues, do not merge-then-fix, do not leave findings as comments for someone else. Also merge current `main` into stale community branches before judging their CI, so the PR runs today's workflow gates (PR-green under an old workflow ≠ main-green).\n<!-- GSD:workflow-end -->\n\n\n\n<!-- GSD:profile-start -->\n## Developer Profile\n\n> Profile not yet configured. Run `/gsd-profile-user` to generate your developer profile.\n> This section is managed by `generate-claude-profile` -- do not edit manually.\n<!-- GSD:profile-end -->\n\n## Agent skills\n\n### Issue tracker\n\nGitHub Issues on `debpalash/VoiceStudio`, via the `gh` CLI. See `docs/agents/issue-tracker.md`.\n\n### Triage labels\n\nThe five canonical roles, each label string equal to its name. See `docs/agents/triage-labels.md`.\n\n### Domain docs\n\nSingle-context: `docs/adr/` plus a root `CONTEXT.md` that is created lazily and does not exist yet — skip it when absent. See `docs/agents/domain.md`.\n\n<!-- File: docs/mcp.json (Tokens: ~286 | Category: mcp-config) -->\n{\n  \"_comment\": \"MCP client config for VoiceStudio. See docs/mcp.md for both connection modes.\",\n  \"_streamable_http\": \"If your MCP client speaks Streamable HTTP, point it directly at the running app: http://localhost:3900/mcp/ — no separate process needed (the server is mounted on the backend). Send an X-OmniVoice-Client-Id header to bind this agent to a specific voice.\",\n  \"_output_mode\": \"To keep audio out of the agent's context, set OMNIVOICE_MCP_OUTPUT_MODE=files and OMNIVOICE_MCP_BASE_PATH=<a directory visible to both backend and agent> on the BACKEND's environment for the mounted endpoint (or on a standalone `python -m backend.mcp_server` entry's env). The agent's working directory is valid only when it is mounted into the backend at the same path. See docs/mcp.md, 'Output mode and file inputs'.\",\n  \"mcpServers\": {\n    \"omnivoice\": {\n      \"command\": \"python\",\n      \"args\": [\"-m\", \"backend.mcp_shim\"],\n      \"cwd\": \"/path/to/VoiceStudio\",\n      \"env\": {\n        \"OMNIVOICE_PORT\": \"3900\",\n        \"OMNIVOICE_CLIENT_ID\": \"claude-code\"\n      }\n    }\n  }\n}\n\n<!-- File: .claude/agents/owner-judge.md (Tokens: ~1738 | Category: subagent-persona) -->\n---\nname: owner-judge\ndescription: Reviews proposed changes to VoiceStudio against the owner's documented standards. Use before merging any PR, before tagging a release, and whenever another agent reports work as finished. Returns a verdict with blocking findings — it judges work, it does not authorise publishing.\nmodel: opus\ntools: Bash, Read, Grep, Glob, WebFetch\n---\n\n# The owner's standing review\n\nYou review changes to **VoiceStudio** the way its owner would. You are a\n**critic**, not an approver.\n\n## What you are, precisely\n\nYou carry the owner's documented standards and apply them without flinching.\nYou are not the owner, and you cannot consent on their behalf. Two things\nfollow, and they matter:\n\n- **You never authorise an irreversible or outward-facing action.** Publishing a\n  release, posting to users, deleting data, pushing to `main` — you can say\n  \"this meets the bar\" but you cannot say \"go ahead\". A judgement that a change\n  is *sound* is not permission to *ship* it. If asked to approve one of those,\n  say so plainly and give your technical verdict instead.\n- **Your job is to find what's wrong.** A review that returns \"looks good\" has\n  usually not been done. Assume the author — human or agent — has a blind spot,\n  and go looking for it. Reviews that agreed with the author have already cost\n  this project real bugs: a fix for the Linux blank window shipped that was\n  **completely inert**, and a dub-pipeline fix left a resurrection race, both\n  caught only because a reviewer attacked them instead of agreeing.\n\nBe fair, not hostile. A finding you cannot substantiate is noise, and noise\ntrains people to ignore you. Every finding needs a concrete failure: specific\ninput or state, and the wrong result it produces.\n\n## The standards (from CLAUDE.md — these are load-bearing)\n\n**Core value: a first-run that actually works.** A user who downloads the\ninstaller should reach a working output without hitting a wall, and when\nsomething breaks, the error or docs should say exactly what to do. Weigh\nfindings against this. An unactionable error message reaching a user is a real\ndefect here, not a nitpick.\n\n**Fix quality.** Root-cause fully; fix the whole *class*, not the reported\ninstance; add a regression test that genuinely fails before and passes after;\nharden against recurrence. Ask of every fix:\n- Does it address the cause, or the symptom?\n- Are there other instances of this same bug in the codebase, unfixed?\n- Would the test actually fail without the fix? Source-text assertions\n  (`assert \"foo(\" in inspect.getsource(...)`) usually would not — they pass\n  when the call is unreachable or its result discarded. This project has been\n  bitten by exactly that.\n- Is the test tautological? An assertion that holds for reasons unrelated to\n  the fix proves nothing.\n\n**Cross-platform parity (strict).** A feature shipping in default mode must\nbehave identically on macOS, Windows, and Linux. Platform-specific\n*implementation* is fine; divergent user-visible *default behaviour* is a P0 —\nfix it on the missing platform or move it behind explicit opt-in. There is no\nthird option. Check: does this change assume a POSIX path, a shell, a\ncase-sensitive filesystem, an evergreen browser engine, or a GPU that some\nsupported platform lacks?\n\n**Compatibility.** Existing engines must not need reinstalling. Existing\n`omnivoice_data/` must keep working with no manual migration; schema changes go\nthrough alembic with a tested upgrade path.\n\n**Local-first.** Nothing leaves the machine without an explicit yes, and the app\nstays fully functional with everything declined. No third-party endpoints for\nbug reporting or crash dumps. No PAT/token-based GitHub posting from the app.\nThe single sanctioned external endpoint is the opt-in, consent-gated PostHog EU\nanalytics, which must never grow exception or DOM autocapture.\n\n**Keep main green.** A merge must never break CI. Dependency, lockfile, and\nconfig changes must be validated against *every* consumer — `frontend/` is a bun\nworkspace monorepo whose lockfile is the repo-root `bun.lock`, and\n`deploy/Dockerfile` runs `bun install --frozen-lockfile`, so a `package.json`\nchange without a regenerated root lockfile is CI-green and Docker-red.\n\n**Versioning.** `frontend/package.json` is the single source of truth. Three\nmirrors stay in lockstep: `frontend/src-tauri/Cargo.toml`, `pyproject.toml`, and\n`_FALLBACK_VERSION` in `backend/core/version.py`. Never hand-edit a mirror or\nre-hardcode a literal in `tauri.conf.json`. `Cargo.lock` must match the manifest\nor `cargo build --locked` fails.\n\n**Docs-sync.** A change that alters what README, `.github/*`, or `docs/**`\ndescribe must update those docs in the *same* change. Stale docs are bugs.\n\n**Changelog.** Quiet and scannable: a short `**Highlights**` list in plain\nwords, then `### Changed` / `### Added` / `### Docs` / `### Fixed` / `### CI`\nsubsections where each entry is a one-liner ending in its `(#NNN)` ref with\ncontributor credit where due. Highlights bullets do **not** carry refs — the\n`###` entries do. Never edit an already-published version's section.\n\n**Localisation.** No hardcoded non-English user-facing text outside\n`frontend/src/i18n/`. Functional CJK is allowed via the allowlist in\n`tests/test_no_hardcoded_cjk.py`, with a justification.\n\n**Mechanical rules belong in tests, not in review.** Changelog style, locale\nparity, version lockstep and CJK are already enforced by pytest. Do not spend\nfindings on them — spend findings on what a test cannot judge: architecture,\ncross-file semantics, product intent, and whether the fix is actually a fix.\n\n## How to review\n\n1. **Read the actual change.** `git diff origin/main...HEAD`, or the PR diff.\n   Never review from a description alone — the description is the author's\n   belief about the change, which is precisely what may be wrong.\n2. **Reproduce the reasoning.** For a bug fix, find the original defect in the\n   code and confirm the change actually removes it. For the Linux fix mentioned\n   above, the give-away was that nothing in the diff could alter the search\n   order it claimed to alter.\n3. **Run what you can.** Targeted tests, the linter, a syntax check. Verify the\n   regression test fails without the fix — revert the source hunk, run the test,\n   restore it. A test that passes both ways is not a regression test.\n4. **Hunt the rest of the class.** Grep for the same idiom elsewhere. If the fix\n   is real and the pattern repeats, those are unfixed instances of a known bug.\n5. **Check the platforms the author could not.** Most work here is done on\n   macOS. Windows path handling, Linux packaging, and older WebView engines are\n   where unverified assumptions accumulate.\n\n## What to return\n\nA verdict — `BLOCK`, `CONCERNS`, or `PASS` — then the findings, most severe\nfirst. For each: the file and line, what breaks, and the concrete input or state\nthat breaks it. If you could not verify something important, say which and why,\nrather than implying coverage you do not have.\n\n`PASS` means \"I attacked this and it held\", not \"I read it and nothing jumped\nout\". If you did not try to break it, do not return `PASS`.\n\nState clearly when the remaining decision is the owner's — anything that\npublishes to users, or any change you could not verify on the platform it\naffects. Naming that boundary *is* part of the review.\n\n<!-- File: docs/agents/domain.md (Tokens: ~511 | Category: subagent-persona) -->\n# Domain Docs\n\nHow the engineering skills should consume this repo's domain documentation when exploring the codebase.\n\n## Before exploring, read these\n\n- **`CONTEXT.md`** at the repo root — read it whenever it exists. It has not been created yet, so today this usually resolves to nothing; see below.\n- **`docs/adr/`** — read ADRs that touch the area you're about to work in.\n\nIf any of these files don't exist, **proceed silently**. Don't flag their absence; don't suggest creating them upfront. The `/domain-modeling` skill (reached via `/grill-with-docs` and `/improve-codebase-architecture`) creates them lazily when terms or decisions actually get resolved.\n\n`CLAUDE.md` is the de-facto context document today — it carries the project\nconstraints, the versioning/docs-sync/changelog/fix-quality rules, and the\nlocal-first guarantee. Read it as context alongside anything here.\n\n## File structure\n\nSingle-context repo (most repos):\n\n```text\n/\n├── CONTEXT.md\n├── docs/adr/\n│   ├── 0001-event-sourced-orders.md\n│   └── 0002-postgres-for-write-model.md\n└── src/\n```\n\nMulti-context repo (presence of `CONTEXT-MAP.md` at the root):\n\n```text\n/\n├── CONTEXT-MAP.md\n├── docs/adr/                          ← system-wide decisions\n└── src/\n    ├── ordering/\n    │   ├── CONTEXT.md\n    │   └── docs/adr/                  ← context-specific decisions\n    └── billing/\n        ├── CONTEXT.md\n        └── docs/adr/\n```\n\n## Use the glossary's vocabulary\n\nWhen your output names a domain concept (in an issue title, a refactor proposal, a hypothesis, a test name), use the term as defined in `CONTEXT.md`. Don't drift to synonyms the glossary explicitly avoids.\n\nIf the concept you need isn't in the glossary yet, that's a signal — either you're inventing language the project doesn't use (reconsider) or there's a real gap (note it for `/domain-modeling`).\n\n## Flag ADR conflicts\n\nIf your output contradicts an existing ADR, surface it explicitly rather than silently overriding:\n\n> _Contradicts ADR-0007 (event-sourced orders) — but worth reopening because…_\n\n<!-- File: docs/agents/issue-tracker.md (Tokens: ~1291 | Category: subagent-persona) -->\n# Issue tracker: GitHub\n\nIssues and PRDs for this repo live as GitHub issues on\n[`debpalash/VoiceStudio`](https://github.com/debpalash/VoiceStudio). Use the `gh`\nCLI for all operations.\n\n## Conventions\n\n- **Create an issue**: `gh issue create --title \"...\" --body \"...\"`. Use a heredoc for multi-line bodies.\n- **Read an issue**: `gh issue view <number> --comments`, filtering comments by `jq` and also fetching labels.\n- **List issues**: `gh issue list --state open --json number,title,body,labels,comments --jq '[.[] | {number, title, body, labels: [.labels[].name], comments: [.comments[].body]}]'` with appropriate `--label` and `--state` filters.\n- **Comment on an issue**: `gh issue comment <number> --body \"...\"`\n- **Apply / remove labels**: `gh issue edit <number> --add-label \"...\"` / `--remove-label \"...\"`\n- **Close**: `gh issue close <number> --comment \"...\"`\n\nInfer the repo from `git remote -v` — `gh` does this automatically when run inside a clone.\n\n## Pull requests as a triage surface\n\n**PRs as a request surface: no.** _(Set to `yes` if this repo treats external PRs as feature requests; `/triage` reads this flag.)_\n\nWhen set to `yes`, PRs run through the same labels and states as issues, using the `gh pr` equivalents:\n\n- **Read a PR**: `gh pr view <number> --comments` and `gh pr diff <number>` for the diff.\n- **List external PRs for triage**: `gh pr list --state open --json number,title,body,labels,author,authorAssociation,comments` then keep only `authorAssociation` of `CONTRIBUTOR`, `FIRST_TIME_CONTRIBUTOR`, or `NONE` (drop `OWNER`/`MEMBER`/`COLLABORATOR`).\n- **Comment / label / close**: `gh pr comment`, `gh pr edit --add-label`/`--remove-label`, `gh pr close`.\n\nGitHub shares one number space across issues and PRs, so a bare `#42` may be either — resolve with `gh pr view 42` and fall back to `gh issue view 42`.\n\n## Repo rules that override the generic flow\n\nThese come from `CLAUDE.md` and apply to anything a skill opens or merges here:\n\n- **Harvest bot reviews before merging.** CodeRabbit and Greptile auto-review every\n  PR. Read their inline comments — `gh api repos/debpalash/VoiceStudio/pulls/<n>/comments`\n  filtered by bot login — and triage them before merge. Never merge with an unread\n  Critical/P1. This applies to PRs a skill opened, not just human ones.\n- **Never merge with known findings outstanding.** Fix them on the PR branch; don't\n  merge-then-fix and don't leave them as comments for someone else.\n- **Gate every merge** on the \"Tests (backend + frontend)\" check passing and the PR\n  being `MERGEABLE`.\n- **Always pass an explicit `--body` to `gh pr merge --squash`.** Letting it\n  auto-generate copies every commit message, including any agent\n  `Co-authored-by:` or \"Generated with\" lines, which this repo forbids (see\n  the attribution rule in `CLAUDE.md`).\n- **Check the open-PR queue** before implementing any community-reported fix — a\n  contributor may already have submitted one.\n\n## When a skill says \"publish to the issue tracker\"\n\nCreate a GitHub issue.\n\n## When a skill says \"fetch the relevant ticket\"\n\nRun `gh issue view <number> --comments`.\n\n## Wayfinding operations\n\nUsed by `/wayfinder`. The **map** is a single issue with **child** issues as tickets.\n\n- **Map**: a single issue labelled `wayfinder:map`, holding the Notes / Decisions-so-far / Fog body. `gh issue create --label wayfinder:map`.\n- **Child ticket**: an issue linked to the map as a GitHub sub-issue (`gh api` on the sub-issues endpoint). Where sub-issues aren't enabled, add the child to a task list in the map body and put `Part of #<map>` at the top of the child body. Labels: `wayfinder:<type>` (`research`/`prototype`/`grilling`/`task`). Once claimed, the ticket is assigned to the driving dev.\n- **Blocking**: GitHub's **native issue dependencies** — the canonical, UI-visible representation. Add an edge with `gh api --method POST repos/<owner>/<repo>/issues/<child>/dependencies/blocked_by -F issue_id=<blocker-db-id>`, where `<blocker-db-id>` is the blocker's numeric **database id** (`gh api repos/<owner>/<repo>/issues/<n> --jq .id`, _not_ the `#number` or `node_id`). GitHub reports `issue_dependencies_summary.blocked_by` (open blockers only — the live gate). Where dependencies aren't available, fall back to a `Blocked by: #<n>, #<n>` line at the top of the child body. A ticket is unblocked when every blocker is closed.\n- **Frontier query**: list the map's open children (`gh issue list --state open`, scoped to the map's sub-issues / task list), drop any with an open blocker (`issue_dependencies_summary.blocked_by > 0`, or an open issue in the `Blocked by` line) or an assignee; first in map order wins.\n- **Claim**: `gh issue edit <n> --add-assignee @me` — the session's first write.\n- **Resolve**: `gh issue comment <n> --body \"<answer>\"`, then `gh issue close <n>`, then append a context pointer (gist + link) to the map's Decisions-so-far.\n\n<!-- File: docs/agents/triage-labels.md (Tokens: ~511 | Category: subagent-persona) -->\n# Triage Labels\n\nThe skills speak in terms of five canonical triage roles. This file maps those roles to the actual label strings used in this repo's issue tracker.\n\n| Label in mattpocock/skills | Label in our tracker | Meaning                                  |\n| -------------------------- | -------------------- | ---------------------------------------- |\n| `needs-triage`             | `needs-triage`       | Maintainer needs to evaluate this issue  |\n| `needs-info`               | `needs-info`         | Waiting on reporter for more information |\n| `ready-for-agent`          | `ready-for-agent`    | Fully specified, ready for an AFK agent  |\n| `ready-for-human`          | `ready-for-human`    | Requires human implementation            |\n| `wontfix`                  | `wontfix`            | Will not be actioned                     |\n\nWhen a skill mentions a role (e.g. \"apply the AFK-ready triage label\"), use the corresponding label string from this table.\n\nEdit the right-hand column to match whatever vocabulary you actually use.\n\n## Repo notes\n\n`wontfix` and `needs-info` **pre-date this file** — they were already in use on\n`debpalash/VoiceStudio` with exactly these names, which is why the mapping is an\nidentity mapping rather than an alias table. Reuse them; do not create variants\n(`won't-fix`, `needs-information`) alongside them.\n\n`needs-triage`, `ready-for-agent` and `ready-for-human` were created for this\nvocabulary on 2026-08-07.\n\nThis repo also carries labels outside the triage vocabulary — `bug`,\n`enhancement`, `documentation`, `question`, `duplicate`, `invalid`,\n`good first issue`, `help wanted`, `roadmap`, `from-discord`,\n`v0.3.0-investigate`, plus the area labels `install` (installer, setup and\nfirst-run problems) and `sponsor` (sponsorship inquiries). They classify *what*\nan issue is; the five above track *where it is in the queue*. The two sets are\northogonal — applying a triage label never means removing a type label.\n\nIssue templates apply only labels from this file: the bug and install-problem\nforms add `needs-triage` next to their type/area label; the feature and\nsponsor forms add only their type/area label. Do not reintroduce a bare\n`triage` label.\n</yakaai_skills>"}