# CONTEXT.md — Domain Glossary Domain terms used across Sokuji. Use these names exactly in code, docs, and design discussions. ## Provider domain - **Provider** — one AI translation backend: a definition in `src/providers//`. The registry lists ten, in the picker's order: Kizuna AI (the managed Soniox), Local Inference, Gemini, Doubao AST 2.0 (Volcengine AST2), Qwen LiveTranslate, OpenAI Realtime, OpenAI Translate, OpenAI Live, Soniox, Palabra; development builds add the `fake` providers. Several may sit behind a feature flag (`flagged`), a platform (OpenAI Live and Qwen LiveTranslate: Electron and the extension) or the Kizuna umbrella (`VITE_ENABLE_KIZUNA_AI`), so a given build offers a subset. Identified by the definition's `id`, the old `Provider` enum's spelling (`src/types/Provider.ts`) but for `localInference` (`LEGACY_PROVIDER_IDS`). The id is an identifier only — its settings persist under the definition's `settings.key`, the old slice key, which may differ from it (e.g. `openai_translate` → `openaiTranslate`; `LEGACY_SLICE_KEYS`, `src/lib/session/storedSettings.ts`). Local Native is not in the registry: it still runs the old path until kizuna-ai-lab/sokuji#578. - **Provider definition** — the object that answers *every* question about one provider (`Provider`, `src/lib/provider/types.ts`): its settings (`key`, `defaults`, `legacyKeys`, `migrate`) and its `Settings` view, its credentials (`keys`, `fields`, `read`), its readiness `check`, its languages (`sources`, `targets`, `initial`, `reverse`), the capabilities generic code reads (`speech`, `textInput`, `boundaries`, `turns`), `build` / `describe` for one leg's config, `start` (its adapter) and optional session hooks. Adding a provider means one folder, one registry line and its order tests, and locale entries only when new (see CLAUDE.md's "Adding a New AI Provider" recipe for the full checklist). The old path's equivalent, **ProviderDescriptor** (`src/services/providers/ProviderDescriptor.ts`), survives only as `LocalNativeProviderConfig`, until #578. - **Provider Registry** — `src/providers/registry.ts`: one list in the picker's order, the single source of truth for which providers exist. `isPresent` (`src/lib/provider/presence.ts`) decides which a build and platform offer, from the definition's `platforms`, `kind`, `flagged` and `testerSwitch`: `VITE_ENABLED_PROVIDERS` names the flagged ones a release offers, `VITE_ENABLE_KIZUNA_AI` gates the managed one. No module-side-effect self-registration. The old registry, `ProviderConfigFactory`, holds Local Native alone until #578. - **Provider settings** — one provider's user settings (`S`), held by `providerStore` (`src/stores/providerStore.ts`) and stored under `settings..*`. A load reads each field of `defaults`, the credentials, the `legacyKeys` and the pair, runs `migrate`, and writes nothing back. `settingsStore` keeps the common settings and the old path's `localNative` slice. - **Credentials** — what a definition's `credentials.read(values, auth)` answers: the provider's own record (`R`), or `{ missing }` when a field is empty or the sign-in is absent. The credential form draws `credentials.fields(s)`; each value persists at `settings..`, and callers never name provider-specific fields. The old path's `extractCredentials` shape is `LocalNativeProviderConfig`'s alone. - **Managed provider** — Kizuna AI's own service on a third-party engine: Kizuna Soniox (`kizunaai_soniox`, `src/providers/soniox/kizuna.ts`), `managed(base, …)` (`src/lib/provider/managed.ts`) over Soniox's definition — the sign-in in place of a key, and a lease (`lease.ts`) that buys each stream's key from the backend per run. The relay twins (`kizunaai_openai_translate`, `kizunaai_volcengine_ast2`) are deleted, not ported; a stored selection of one resolves to Kizuna Soniox (`MANAGED_LEGACY_IDS`, `src/lib/session/storedSettings.ts`). - **Local Inference vs Local Native** — two PEER providers, same rank as OpenAI or Gemini; NOT two adapters of one shared inference seam. Local Inference runs models in the browser (WASM/WebGPU workers, models in IndexedDB) so it works everywhere; Local Native runs the Python sidecar (WS-RPC, models on the filesystem) for better hardware utilization. They may offer similarly-named models built from the same base weights, but the model repos, runtimes, and readiness stores (`modelStore` vs `nativeModelStore`) are deliberately separate. Local Inference is a provider of the new structure (`src/providers/localInference/`); Local Native still runs the old path (`LocalNativeClient`, `LocalNativeProviderConfig`) until #578 ports it beside it. Do not introduce a unifying layer between them. - **Leg config** — what a provider's adapter starts one leg with (`C`): built by the definition's `build(context, s, shared)` from its settings and the run's shared settings, and handed to `start`. The old path's **SessionConfig** (`src/services/interfaces/IClient.ts`) is `LocalNativeSessionConfig` alone, handed to `IClient.connect()`. ## Native sidecar model resolution - **Model catalog card** — one row of the sidecar's `catalog.py` (`AsrModel`, `TranslateModel`, `TtsModel`) describing one native model: its `Deployment`s (backend, tier — `gpu-metal`, `gpu-vulkan` or `cpu` — quant, and the artifact: one pinned GGUF on the Hub, which `native_models.py` downloads) plus per-model facts — `graph_family` (the op-coverage key), the translation cards' chat-template thinking flags and prompt family, the TTS cards' audio.cpp family and voice facts. The card is the single source of truth for model-specific facts; the sidecar reads them declaratively rather than special-casing by model-id substring, and an id that is no row is unknown (`catalog.resolve_tts_card`). One deliberate exception stays imperative: a loaded TTS model's streaming, cloning and sample rate are read off the loaded model (`tts_backend.py`, from `sokuji_native`'s capabilities). The renderer reads the catalog over the sidecar's wire (`src/lib/local-inference/native/nativeCatalog.ts`). - **Planner / Loader** — the two halves of native model resolution. The **Planner** (pure, `planner.py`) turns `(card, Machine, bench, downloaded, op coverage)` into ranked `Plan`s — tier gating (`TIER_RANK`; a paravirtual Metal device is no `gpu-metal`), quant selection, and the op-coverage gate (only TTS refuses a rung) — with no I/O, so it is table-testable without monkeypatching. The **Loader** (effectful, `accel.py`) probes the devices through `sokuji_native` (`native.py`, the sidecar's one door to it), loads a backend from the downloaded weights behind the VRAM fallback gate, and benchmarks; `native_models.py` downloads them. Split around the deep islands (the `load_with_fallback` VRAM gate stays in the Loader), not through them. The backends (`asr_backend.py`, `translate_backend.py`, `tts_backend.py`) run transcribe.cpp, llama.cpp and audio.cpp on one ggml (`native/`; CLAUDE.md's "Native runtime"). - **Plan / Plan.config** — a `Plan` is one resolved deployment (backend, tier, device, quant, artifact) the Loader can execute. `Plan.config` (`PlanConfig`) carries card-derived backend hints — the thinking flags and prompt family for translation; the TTS family, its load-time language and its extra files — so a backend receives plain config at `load()` and stays decoupled from the catalog card types. ## Session domain - **Adapter** — one leg's client of a provider's realtime protocol: `adapter.ts` in the provider's folder, implementing L0 (`src/lib/contract/adapter.ts`) — a started session emits segments, audio and lifecycle through `AdapterEvents` — and held to the conformance suite (`src/lib/contract/conformance.ts`). Reached only through its definition's `start`. The old path's **Client** (`IClient`, `src/services/interfaces/IClient.ts`) survives only as `LocalNativeClient`, until #578. - **SidecarConnection** — the WS-RPC transport seam behind the Local Native clients (`ISidecarConnection` is the interface the clients depend on and tests substitute). Owns one socket to the Python sidecar and the mechanics every native client shared: connect, id-correlated request/reply, fire-and-forget send, outbound binary, and routing of un-correlated push messages. The *connection* is the unit, not a shared socket — each native stage client (ASR / translate / TTS / model) holds its own, because the sidecar routes binary frames and frees VRAM per-connection. Native-only: the browser (WASM) side of Local Inference talks to workers, not a sidecar, so it has no equivalent — do not generalize this into a cross-provider transport. - **Segment** — the transcript unit: a source or translation segment with its text, speech and pairing, which L1 (`src/lib/conversation/Conversation.ts`, one per leg) folds an adapter's events into and L2 projects for the surfaces. The old path's **ConversationItem** (`IClient.ts`) is `LocalNativeClient`'s alone. ## Extension domain - **Platform registry** — `extension/platforms.ts`: one row per supported meeting platform (hostname, match pattern, content-script profile, names, optional group, guidance i18n key, site-plugin key). The single source of truth. Icons live in the sibling `extension/platformIcons.ts` (keyed by hostname) so the icon-free registry doesn't bundle ~11 KB of base64 into the subtitle surface / main app / vanilla scripts — only popup.js imports the icons. Bundled consumers (popup, subtitle surface) import the registry; vanilla copied scripts (background.js, content.js) read a build-emitted `platforms.generated.js`. `site-plugins.js` is the one exception: it runs in the page's MAIN world (not the isolated world the generated global lives in), so it keeps its own inline `HOST_TO_PLUGIN_KEY` map, guarded by a consistency test that parses the file and diffs it against the registry. `manifest.json` stays hand-authored but is guarded by consistency tests. `app.slack.com` is the canonical Slack host (never `slack.com`).