Skip to content

Feature gates for core subsystems — tracking (lightweight harness builds) #4795

Description

@senamakel

Problem

A lightweight harness build of the core today still carries everything: workflows/flows, skills, MCP, meet, webviews/channels, web3/wallet, voice, media generation, and ~130 other domains. Two costs:

  1. Runtime bloatbuild_registered_controllers() in src/core/all.rs unconditionally registers every domain's controllers; the agent tool surface, store init, and bus subscribers follow. Even ServiceSet::none() (from feat(core): add pluggable core runtime and fleet host #4791) only skips background services — the full RPC/tool surface still initializes. A harness that wants "agent loop + memory + threads" pays for all of it: startup time, memory, tool-surface/prompt bloat, attack surface.
  2. Compile-time bloat — every domain compiles into every binary. Cargo [features] today only cover leaf concerns (tokenjuice-treesitter, sandbox-*, whatsapp-web, e2e-test-support), not subsystem families. Embedders (examples/embed_headless.rs, openhuman-fleet, stdio-MCP hosts) can't build a slim core.

Approach

Group subsystems behind per-family feature gates, one tracked issue per gate (linked below). Each gate spans two layers:

  • Cargo feature (compile-time): sheds the domain's crates/deps from the build. Default-on — the Tauri desktop app always builds with all gates enabled; shipped product is unchanged.
  • DomainSet flag (runtime): a selector on CoreBuilder (src/core/runtime/builder.rs) next to ServiceSet, so embedders can further narrow at runtime what was compiled in. DomainSet::full() is the default; DomainSet::harness() = agent + memory + threads + config + security only.

Effects of a disabled gate: controllers not registered (unknown-method over RPC), agent tools absent, stores not initialized, bus subscribers not registered, /schema reflects the actual surface.

The clean seam is the phase-2 DomainRegistration collapse already planned in docs/plans/pluggable-core/README.md — once each domain registers via a single DomainRegistration entry (controllers + tools + stores + subscribers), gating is one filter over that list instead of scattered ifs.

Per-gate definition of done (applies to every child issue)

  • Cargo feature added to root Cargo.toml, in default; Tauri shell builds unchanged with all gates on.
  • DomainSet flag wired through registration, store init, and subscriber registration.
  • E2E with gate enabled: full existing suites pass unchanged.
  • E2E with gate disabled: build compiles, core boots and serves /rpc, /schema omits the gated namespaces, gated RPC methods return unknown-method, agent tool list omits gated tools.
  • CI smoke covering the disabled combination (e.g. matrix cargo check/boot-test with the gate off).
  • Docs updated (AGENTS.md + architecture).

Child issues

Non-goals

  • No wire-contract or controller-schema changes.
  • No per-user/tenant gating — this is per-build/per-host composition (autonomy tiers and SecurityPolicy remain the per-user control).
  • Not a replacement for ServiceSet — orthogonal axes: ServiceSet = what runs in the background; DomainSet = what exists at all.

Relationship to existing work

  • feat(core): add pluggable core runtime and fleet host #4791 (CoreBuilder/CoreRuntime/ServiceSet, fleet host) — this is the missing second axis of that composition story.
  • docs/plans/pluggable-core/phase-2-corecontext.md — the DomainRegistration collapse is the prerequisite seam; this effort is a strong argument for prioritizing it.

Metadata

Metadata

Assignees

Labels

rust-coreCore Rust runtime in src/: CLI, core_server, shared infrastructure.taskWork item that is not primarily a bug or a feature.

Type

No type

Fields

No fields configured for issues without a type.

Projects

Status
Todo

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions