Skip to content

feat(core): compile-time voice feature gate (voice + audio_toolkit) (#4803) - #4833

Merged
senamakel merged 5 commits into
tinyhumansai:mainfrom
oxoxDev:feat/4803-voice-feature-gate
Jul 14, 2026
Merged

feat(core): compile-time voice feature gate (voice + audio_toolkit) (#4803)#4833
senamakel merged 5 commits into
tinyhumansai:mainfrom
oxoxDev:feat/4803-voice-feature-gate

Conversation

@oxoxDev

@oxoxDev oxoxDev commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Problem

#4795 wants one compile-time feature gate per subsystem family so slim harness builds drop code + deps; #4796 shipped the runtime DomainSet axis. This PR adds the compile-time half for voice. Two scope realities the issue under-stated, confirmed by a full sweep:

  • whisper-rs / llama are NOT dropped by this gate. They live in the inference domain (src/openhuman/inference/local/service/whisper_engine.rs); cpal is shared with accessibility. Only hound (voice) and lettre (audio_toolkit) are exclusive to the gated domains. Whisper awaits a separate future inference gate. The issue-level DoD line claiming whisper drops is superseded (noted in AGENTS.md).
  • voice is widely consumed (credentials startup, channels reply-speech/STT, dictation websocket, socketio, meet_agent, desktop_companion) — ~22 call sites — so it cannot be a clean leaf removal.

Solution

  • Cargo.toml: hound + lettreoptional = true; voice = ["dep:hound", "dep:lettre"]; voice added to default.
  • Facade (src/openhuman/voice/mod.rs): real submodules + inference re-exports are #[cfg(feature="voice")]; new src/openhuman/voice/stub.rs (#[cfg(not(feature="voice"))]) re-exposes the exact caller surface (server, dictation_listener, streaming, reply_speech, cloud_transcribe, cli, create_stt_provider, effective_stt_provider, publish_ptt_transcript_committed) with no-op / None / disabled-error bodies matching the real signatures.
  • audio_toolkit: whole module #[cfg(feature="voice")]; its 3 podcast agent tools + registration + the voice controller/CLI registration in src/core/all.rs are #[cfg]'d out when off.
  • CI: new rust-feature-gate-smoke lane runs cargo check --no-default-features --features tokenjuice-treesitter — the disabled build is the only thing that catches stub-signature drift, so it must run in CI.
  • Slim-profile convention (no full meta-feature): cargo build --no-default-features --features "<explicit gates>". Documented in AGENTS.md.

When off: voice/audio controllers are unknown-method over /rpc and absent from /schema, the audio_generate_podcast tools are absent, openhuman voice returns a disabled error.

Submission Checklist

  • Tests added or updated (happy path + at least one failure / edge case) per Testing Strategy
  • N/A: no instrumented changed lines — the diff is compile-config only (#[cfg] attrs, optional deps, a cfg(not(feature="voice")) stub module not compiled in the default/coverage build, docs, CI yaml). diff-cover reports "no lines with coverage information"; the two new registration tests cover the on/off behavior. CI coverage-gate authoritative. — Diff coverage ≥ 80%
  • Coverage matrix updated — N/A: compile-time build-config change, no user-facing feature row
  • All affected feature IDs from the matrix are listed in the PR description under ## RelatedN/A: no matrix rows affected
  • No new external network dependencies introduced (mock backend used per Testing Strategy)
  • N/A: default build is byte-identical; the gate only removes surface when explicitly disabled — Manual smoke checklist
  • Linked issue closed via Closes #NNN in the ## Related section

Impact

  • Desktop / CLI / mobile / web: no behavior change — default build keeps voice on and is byte-identical.
  • Slim builds: --no-default-features drops the voice/audio domains + hound/lettre. Note: whisper/cpal are NOT dropped (inference-owned).
  • Soft dependency: with {voice: off} but Meet/companion on, their speech paths hit the disabled stubs (transcription/synthesis no-op, not a crash). Acceptable for slim profiles; whether the Meet gate should imply voice is a follow-up.
  • Security / migration: none. Additive, default-preserving.

Related


AI Authored PR Metadata (required for Codex/Linear PRs)

Linear Issue

  • Key: N/A
  • URL: N/A

Commit & Branch

  • Branch: feat/4803-voice-feature-gate
  • Commit SHA: d48ae12fd17b2d07e23a26818a10e227d84681c9

Validation Run

  • N/A: no app/ (frontend) changes — pnpm --filter openhuman-app format:check
  • N/A: no TypeScript changes — pnpm typecheck
  • Focused tests: core::all::tests::voice_and_audio_controllers_registered_when_feature_on (default) + ..._absent_when_feature_off (disabled), core::all 50 passed, openhuman::voice/openhuman::audio_toolkit green
  • Rust fmt/check (if changed): cargo fmt --check clean · default cargo check exit 0 · disabled cargo check --no-default-features --features tokenjuice-treesitter exit 0 · cargo clippy --lib 0 warnings in changed files (both configs)
  • N/A: no app/src-tauri changes — Tauri fmt/check

Validation Blocked

  • command: cargo test --lib (full)
  • error: OOM on local machine (known)
  • impact: full matrix runs in CI; locally scoped to voice/audio_toolkit/core::all/tools::ops — all green in both feature configs

Behavior Changes

  • Intended behavior change: new default-on voice compile-time gate; default unchanged
  • User-visible effect: none by default; slim builds omit voice/audio domains + deps

oxoxDev added 5 commits July 13, 2026 23:02
…inyhumansai#4803)

Introduce a compile-time `voice` Cargo feature (default-ON) that pulls the
now-optional `hound` (WAV I/O) and `lettre` (podcast email) dependencies.
Default builds are byte-identical; slim builds drop the pair via
`--no-default-features`. whisper-rs / cpal are intentionally left untouched
(inference domain — future gate).
…ed stub (tinyhumansai#4803)

Keep `pub mod voice;` always compiled as a facade: real submodules and the
inference::voice re-exports are gated `#[cfg(feature = "voice")]`, and a new
`#[cfg(not(feature = "voice"))] mod stub` mirrors the public surface that
always-on / other-gated callers depend on (server, dictation_listener,
streaming, reply_speech, cloud_transcribe, cli, create_stt_provider,
effective_stt_provider, publish_ptt_transcript_committed) with
no-op / None / disabled-error bodies. Callers need no per-call cfg; the
disabled build catches any signature drift.
… behind voice (tinyhumansai#4803)

Compile out the `audio_toolkit` module, its controller + voice-controller
registration in core::all, and the three podcast agent tools + tool re-export
when the `voice` feature is off. The voice CLI adapter stays registered so
`openhuman voice` returns a clear disabled error via the facade stub. Add
registry assertions covering both feature configs (controllers present when
on, absent when off).
…ion (tinyhumansai#4803)

Add a Compile-time domain gates section to AGENTS.md: the default-on `voice`
feature, the facade/stub pathfinder pattern, the slim-profile
`--no-default-features --features "<explicit list>"` convention, and the
scope correction that whisper-rs / llama / cpal are NOT dropped by this gate
(inference domain, future gate).
DoD for tinyhumansai#4803 requires CI to build the core with the gate OFF — the disabled
build is the only thing that catches stub-facade signature drift. Adds a
rust-feature-gate-smoke lane running
`cargo check --no-default-features --features tokenjuice-treesitter`.
Pathfinder lane; extend the --features list as sibling gates land.
@oxoxDev
oxoxDev requested a review from a team July 13, 2026 17:46
@oxoxDev oxoxDev added this to the M1 — Big compile wins milestone Jul 13, 2026
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

An error occurred during the review process. Please try again later.


Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d48ae12fd1

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +359 to +361
rust-feature-gate-smoke:
name: Rust Feature-Gate Smoke (gates off)
needs: [changes]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Wire feature-gate smoke into the PR gate

In PRs where the repository rules only require the historical PR CI Gate check (the workflow comment says that name is kept for the ruleset), this new smoke job can fail without blocking merge because pr-ci-gate neither lists rust-feature-gate-smoke in its needs nor checks its result. That defeats the stated purpose of this lane: a future stub-signature drift in --no-default-features --features tokenjuice-treesitter could be red in CI while the required gate still passes.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(core): feature gate — voice

2 participants