Files
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

4.0 KiB

Feature Flags

Feature flags in Tutti are pure config distribution: durable storage in daemon preferences, push to clients over the eventstream, a key registry, and a query helper. The infrastructure is semantics-free — it stores and distributes map[string]bool and nothing more. Each feature owns what "off" means; that logic never belongs to the flag infrastructure.

Taxonomy

  • Capability flags gate daemon-enforced behavior (writes, orchestration, runtime operations). The daemon must enforce them server-side so toggling the UI cannot bypass the gate. Query them through the daemon registry helper, never by poking the raw map.
  • UI-preference flags only show or hide renderer surfaces. The renderer catalog is sufficient; no daemon enforcement is required.

A flag can start as UI-preference and gain daemon enforcement later; keep the same key when that happens.

lab.connectors is a capability flag whose owning surfaces span renderer settings, daemon composition, and daemon-projected Composer Options. The daemon reads it fail-closed during startup. When it is off, the Connector market, runtime, MCP gateway, Agent runtime projection, and tutti connector command provider are not constructed; consequently Connector policy is not injected into Agent system prompts. Existing installed state remains on disk. Changing the flag takes effect for daemon-owned Connector capabilities after the daemon restarts. Renderer off semantics also remove the Connectors settings entry, connector setup deep links, and connector entries from the Agent composer, and the AgentGUI footer uses Tutti Mode as that slot's fallback. Renderer projections must filter cached connector palette rows while the daemon-backed Composer Options reread is in flight.

Key contract

The daemon registry is the key contract:

  • Go: services/tuttid/biz/preferences/lab_flags.go
  • Renderer mirror: apps/desktop/src/shared/featureFlags/catalog.ts

Both must carry identical keys and defaults. When adding, renaming, or removing a flag, change both sides in the same change. Storage and push are already generic (DesktopPreferences.FeatureFlags, NormalizeDesktopFeatureFlags, preferences eventstream updates), so a new flag only needs registry entries and copy.

When a feature graduates, remove its registry entries and every owning-feature gate in the same change. Historical stored values may remain in generic preferences for compatibility, but graduated features must not consult them; this makes the feature available to existing profiles even when their old value was false.

Resolution rule on both sides: a stored value wins; absent keys fall back to the registry default; absent unregistered keys resolve to false (IsLabFlagEnabled in Go, isFeatureEnabled in TS).

Defaults and off semantics

  • Defaults are fail-closed: every Lab flag defaults to false. A flag that must default on needs an explicit product decision recorded in the PR.
  • Recommended default-off semantics (guidance, not a mandate): while a flag is off, new writes are rejected or hidden, but existing data and already running behavior are left unaffected. The owning feature decides and documents its exact semantics.

Naming

  • lab.* for Lab experiments surfaced in the Lab settings section.
  • Domain-scoped dotted keys for everything else, for example agent.extension.<source> or browser.chromeCookieImport.
  • Keys are lowercase camelCase segments joined by dots.

Existing reference pattern

services/tuttid/service/agentextension/manager.go is the existing example of feature-owned semantics: stable sources are enabled by generated product configuration and ignore retired stored activation values, while Early Access sources derive their own keys ("agent.extension."+source.Key) and decide what disabled means (reconcile and stop). New consumers should prefer registry constants and IsLabFlagEnabled over poking the raw map, while keeping their own off and graduation semantics in the owning feature, exactly as the Agent Extension manager does.