Skip to content

feat(core): compile-time meet feature gate (#4800)#4915

Open
oxoxDev wants to merge 7 commits into
tinyhumansai:mainfrom
oxoxDev:feat/4800-meet-feature-gate
Open

feat(core): compile-time meet feature gate (#4800)#4915
oxoxDev wants to merge 7 commits into
tinyhumansai:mainfrom
oxoxDev:feat/4800-meet-feature-gate

Conversation

@oxoxDev

@oxoxDev oxoxDev commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Adds a compile-time Cargo meet feature (default-ON) gating meet (562 LOC) + meet_agent (5,298) + agent_meetings (8,909) — ≈14.7k LOC — composing with the runtime DomainSet::meet flag from feat(core): DomainSet on CoreBuilder + DomainRegistration filter seam (feature-gate prerequisite) #4796.
  • Default build is byte-identical — every change is cfg-off-only. Slim builds opt out via cargo build --no-default-features --features "<gates without meet>".
  • A load-bearing carve-out: meet_agent::wav::pack_pcm16le_mono_wav stays ungated because the always-on desktop_companion STT path calls it. Stubbing it would compile clean and silently feed a 0-byte WAV to cloud STT.
  • Sheds zero dependencies (meet = []) — the dep shed was pre-paid, see below.
  • Pattern: leaf-gate (meet) + facade/carve-out no-stub (meet_agent) + facade+stub (agent_meetings).

Problem

#4795 wants one compile-time feature gate per subsystem family; #4796 shipped the runtime DomainSet axis. This PR adds the compile-time half for the Meet family.

Three of the epic's DoD bullets are inapplicable here. Stating them with evidence rather than leaving boxes that imply missing work:

The real risk in this family is not the gate — it is the carve-out below.

Solution

  • Cargo.toml: meet = [] added to default — dep list intentionally empty, commented so nobody "fixes" it later.
  • The load-bearing carve-out. meet_agent::wav::pack_pcm16le_mono_wav stays compiled in all builds: the always-on desktop_companion domain (Platform group) calls it to pack PCM for STT. This is verified, not assumed — deliberately gating it produces error[E0433]: cannot find 'wav' in 'meet_agent', then reverted. So the warning in the module doc is tested, not aspirational. Note the failure mode this avoids: a stub here would compile clean and silently hand a 0-byte WAV to cloud STT — a silent-corruption bug, not a build error.
  • Leaf-gate for meet (registration sites want absence, so no stub).
  • Facade/carve-out, no stub for meet_agent — the module facade stays, wav stays compiled, the live STT/LLM/TTS loop is gated.
  • Facade+stub for agent_meetingsstub.rs mirrors the always-on caller surface with disabled-error / empty bodies, so core/all.rs needs no call-site cfg.
  • App forwarding (app/src-tauri/Cargo.toml): openhuman_core is default-features = false, so meet is added explicitly to keep the domain in the shipped desktop app. Verified via cargo tree -e features -i openhuman.
  • CI: no change needed — the rust-feature-gate-smoke lane is a deny-by-default allow-list (--no-default-features --features tokenjuice-treesitter), so a new default-ON gate is excluded automatically and the disabled combination is already covered.
  • Docs (AGENTS.md): gate-table row + the wav carve-out and its inverted dependency.

When off: the meet / meet_agent / agent_meetings namespaces are absent from /schema and their methods return a clean JSON-RPC unknown-method (-32000); desktop_companion STT is unaffected.

Submission Checklist

If a section does not apply to this change, mark the item as N/A with a one-line reason. Do not delete items.

  • Tests added or updated (happy path + at least one failure / edge case) per Testing Strategy — both-direction gate tests in core/all_tests.rs; the wav carve-out verified by deliberately gating it and observing the compile error.
  • N/A: no instrumented changed lines — the diff is compile-config only (#[cfg] attrs, a Cargo feature, a stub facade, docs); diff-cover reports no coverable lines. The directional gate tests cover the on/off behaviour. — Diff coverage ≥ 80%
  • N/A: compile-time build-config change, no user-facing feature row — Coverage matrix updated
  • N/A: no matrix rows affected — All affected feature IDs from the matrix are listed in the PR description under ## Related
  • No new external network dependencies introduced (mock backend used per Testing Strategy) — no deps added or removed; meet = [].
  • N/A: default build is byte-identical, so no release-cut surface changes — Manual smoke checklist updated if this touches release-cut surfaces (docs/RELEASE-MANUAL-SMOKE.md)
  • Linked issue closed via Closes #NNN in the ## Related section

Impact

  • Desktop / CLI / mobile / web: no behaviour change — default keeps meet on and the build is byte-identical. desktop_companion STT is unaffected in both configs by design (the wav carve-out).
  • Slim builds: drop ≈14.7k LOC and 3 RPC namespaces. No binary-size win from deps — zero crates shed.
  • Performance / security: reduced compile-time surface and attack surface in slim builds (no Meet bot Socket.IO path, no live call loop).
  • Migration / compatibility: none. Additive and default-preserving.

Related


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

Linear Issue

  • Key: N/A — GitHub-issue driven, no Linear ticket.
  • URL: N/A

Commit & Branch

  • Branch: feat/4800-meet-feature-gate
  • Commit SHA: 882798ac63f98a283d04ff47042212fcb7f41c66 (5 commits, 9 files, +186/-4)

Validation Run

  • N/A: no frontend changes — pnpm --filter openhuman-app format:check
  • N/A: no frontend changes — pnpm typecheck
  • Focused tests: scoped enabled-config tests pass; both-direction gate tests pass in their configs.
  • Rust fmt/check (if changed): cargo fmt clean · enabled cargo check 0 errors · disabled cargo check --no-default-features --features tokenjuice-treesitter 0 errors · clippy clean in both directions.
  • N/A: manifest-only change to app/src-tauri/Cargo.toml (one dep line), no Tauri Rust source touched — forwarding verified via cargo tree -e features -i openhuman — Tauri fmt/check (if changed)

Boot smoke (both directions, 2 runs for repeatability) — both configs built, linked, booted, and served /rpc:

  • Gate ON: all 3 namespaces present in /schema.
  • Gate OFF: all 3 namespaces absent; methods return a clean JSON-RPC unknown-method (-32000); the process survives.

Validation Blocked

  • command: cargo test --no-default-features
  • error: 2 pre-existing failures on main today — group_mapping_smoke and harness_excludes_gated_namespaces, both asserting the voice namespace uncfg'd (fallout from the merged voice gate feat(core): feature gate — voice #4803). CI cannot see them: the feature-gate smoke lane runs cargo check, which never compiles test code.
  • impact: Not introduced by this PR and not fixed by it. This PR cfg'd its own asserts and left voice's alone; the voice asserts are a separate, epic-level fix that is pending. Scoped enabled-config tests and both-direction cargo check are green.

Behavior Changes

  • Intended behavior change: new default-ON meet compile-time gate. Default build unchanged.
  • User-visible effect: none by default. Slim builds omit the 3 Meet namespaces. No tools are affected — Meet has none.

Parity Contract

  • Legacy behavior preserved: yes — every change is cfg-off-only, so the default build is byte-identical.
  • Guard/fallback/dispatch parity checks: gate ON reproduces current registration exactly (verified by boot smoke against the live /rpc); gate OFF yields absence at every registration site. The desktop_companion STT path keeps a real wav implementation in both configs — the carve-out is enforced by the compiler (verified by deliberately gating it and observing E0433), not by convention, specifically so it cannot silently degrade to a 0-byte WAV. Composes with, and does not replace, the runtime DomainSet::meet guard from feat(core): DomainSet on CoreBuilder + DomainRegistration filter seam (feature-gate prerequisite) #4796.

Duplicate / Superseded PR Handling

oxoxDev added 5 commits July 15, 2026 17:43
Defines the compile-time gate for the three Meet domains. Default-ON, so
the desktop build stays byte-identical; slim builds opt out via
--no-default-features.

Unlike `voice`, this gate sheds no dependencies — the Meet domains have
zero exclusive crates. `meet_agent::wav` is a hand-rolled RIFF writer
written precisely so Meet never needed `hound`, which `voice` already
owns and sheds. The gate's value is compile-time surface, not the dep
tree; Cargo.lock is unchanged, which confirms it.
…yhumansai#4800)

Applies one module pattern per domain, chosen by whether always-compiled
code reaches a non-registration symbol:

- meet          -> leaf-gate; its only outside reference is the registry.
- meet_agent    -> facade + carve-out, no stub; nothing outside the Meet
                   domain calls its gated submodules.
- agent_meetings -> facade + stub; the heartbeat planner and two
                   subscriber registrations reach in, so stub.rs supplies
                   no-op equivalents and those callers need no cfg.

The stub's no-ops are semantically exact rather than placeholders: a
register_* that registers nothing is the intended disabled behaviour, and
handle_calendar_meeting_candidate returning false means "Meet published no
card", so the planner correctly falls through to its generic reminder.

CARVE-OUT: meet_agent::wav stays ungated — desktop_companion (Platform,
always-on) calls pack_pcm16le_mono_wav and needs the real implementation.
It is dependency-free, so leaving it compiled costs nothing. Verified:
gating it fails the disabled build loudly at desktop_companion/pipeline.rs
with E0433. That failure must be fixed by reverting the cfg, never by
stubbing the function — a stub would trade a compile error for green CI
while silently corrupting companion STT. Recorded in the module doc.
Adds meet_controllers_registered_when_feature_on and its negative twin
meet_controllers_absent_when_feature_off, covering all three namespaces.
The negative half is the one that proves the gate removes anything — a
gate that never dropped a controller would still pass the positive test.

Also cfg's the group_for_namespace("meet") assert in group_mapping_smoke:
the helper is registry-derived, so with meet compiled out the namespace is
absent and the lookup correctly returns None. The neighbouring assert at
:765 needs no change — "meet" is in the *absent* list there, which holds
either way.

Note CI's smoke lane runs cargo check only and never compiles test code,
so a disabled-build test break is invisible to it; run the disabled test
lane locally after touching any gated surface.
The shell depends on the core with default-features = false and had no
features key, so a default-ON gate would silently drop from the shipped
app. Written as a multi-line array so the sibling gates in this epic
append cleanly rather than conflicting on one line.
…umansai#4800)

Records the three module patterns and the rule that picks between them,
the wav carve-out and why stubbing it is dangerous, and the fact that the
gate sheds no dependencies — so that last point isn't re-litigated by the
next reader expecting a voice-style dep drop.
@oxoxDev oxoxDev requested a review from a team July 15, 2026 14:33
@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 26 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 66ca8577-2553-4c5c-90e4-58b3c4351e4c

📥 Commits

Reviewing files that changed from the base of the PR and between d320c43 and 6c4ad4a.

📒 Files selected for processing (9)
  • AGENTS.md
  • Cargo.toml
  • app/src-tauri/Cargo.toml
  • src/core/all.rs
  • src/core/all_tests.rs
  • src/openhuman/agent_meetings/mod.rs
  • src/openhuman/agent_meetings/stub.rs
  • src/openhuman/meet_agent/mod.rs
  • src/openhuman/mod.rs

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: 882798ac63

ℹ️ 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 thread src/core/all.rs
// Google Meet call-join request validation (shell handles the webview)
// Google Meet call-join request validation (shell handles the webview).
// Gated behind the `meet` feature.
#[cfg(feature = "meet")]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Hide disabled Meet capabilities from about_app

When this cfg removes the Meet controllers in --no-default-features builds, the always-on about_app catalog still returns the meet.join_call and meet_agent.live_loop entries unconditionally from src/openhuman/about_app/catalog_data.rs, so openhuman.about_app_list/search/lookup advertises Intelligence > Calls even though the corresponding RPC methods are now method-not-found. The repo instructions describe about_app as the user-facing capability catalog to update when features are removed, so please cfg or filter those catalog entries alongside this gate.

Useful? React with 👍 / 👎.

Comment thread src/core/all.rs
);
// Agent meetings — backend-delegated Meet bot via Socket.IO
// (gated with meet).
#[cfg(feature = "meet")]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Gate the backend Meet socket path as well

This gates the agent_meetings controllers, but the backend Socket.IO Meet path is still compiled and active when meet is off: src/openhuman/socket/event_handlers.rs continues accepting bot:* events and publishing BackendMeet* events, and src/core/socketio.rs still broadcasts those as agent_meetings:* to renderer sockets. In a slim build connected to the backend while a stale or misrouted bot session emits transcripts/replies, the supposedly disabled Meet feature still processes and exposes meeting data; please guard those bot handlers/bridges with the same feature gate.

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 — meet

2 participants