LemonCore.Config.Features (lemon_core v0.1.0)

View Source

Feature flag configuration for Lemon.

Feature flags gate behaviour changes behind config so later milestones can be rolled out incrementally without ad-hoc environment variables.

Configuration

[features]
session_search             = "off"
routing_feedback           = "opt-in"     # enable with "default-on" once gate passes
skill_synthesis_drafts     = "opt-in"     # enable with "default-on" once gate passes

Adaptive feature rollout

routing_feedback and skill_synthesis_drafts are gated by measurable criteria defined in LemonRouter.RolloutGate. Both flags default to "opt-in" (available but inactive) until the quantitative gates pass:

  • routing_feedback: requires ≥50 recorded samples, ≥+5pp success-rate improvement over baseline, and no increase in retry rate.
  • skill_synthesis_drafts: requires ≥20 candidate documents evaluated, ≥60% generation rate, and ≤10% audit false-positive rate.

To check whether a feature is ready to graduate to "default-on", call LemonRouter.RolloutGate.evaluate_routing_feedback/1 or LemonRouter.RolloutGate.evaluate_synthesis/1 with a current metrics snapshot.

To roll back a graduated feature immediately (no restart required for env vars):

export LEMON_FEATURE_ROUTING_FEEDBACK=off
export LEMON_FEATURE_SKILL_SYNTHESIS_DRAFTS=off

See LemonRouter.RolloutGate for full rollback and re-evaluation procedure.

Rollout states

StateMeaning
"off"Feature is fully disabled (kill-switch).
"opt-in"Feature is available but disabled by default; must be explicitly enabled.
"default-on"Feature is enabled unless explicitly disabled.
"on"Alias for "default-on".

Environment variable overrides

Each flag can be overridden via an environment variable using the pattern LEMON_FEATURE_<FLAG_NAME> where <FLAG_NAME> is the flag key in SCREAMING_SNAKE_CASE.

For example:

LEMON_FEATURE_SESSION_SEARCH=opt-in
LEMON_FEATURE_ROUTING_FEEDBACK=default-on

Kill-switch behaviour

Set any flag to "off" to disable the feature regardless of code state. Code gated behind a flag must call LemonCore.Config.Features.enabled?/2 (or the equivalent convenience helpers in LemonCore.Config.Modular) before activating that behaviour.

Summary

Functions

Returns true when the feature is active (state is :default-on or :on).

Returns all known feature flag names as a list of strings.

Resolves feature flags from the merged TOML settings map.

Validates that all feature flag values are recognised rollout states.

Types

rollout_state()

@type rollout_state() :: :off | :"opt-in" | :"default-on"

t()

@type t() :: %LemonCore.Config.Features{
  routing_feedback: rollout_state(),
  session_search: rollout_state(),
  skill_synthesis_drafts: rollout_state()
}

Functions

enabled?(features, flag, opts \\ [])

@spec enabled?(t(), atom(), keyword()) :: boolean()

Returns true when the feature is active (state is :default-on or :on).

Pass an optional opt_in: true keyword to also accept the :"opt-in" state (used when the caller explicitly wants to enable an opt-in feature).

Features.enabled?(features, :session_search)
Features.enabled?(features, :session_search, opt_in: true)

flag_names()

@spec flag_names() :: [String.t()]

Returns all known feature flag names as a list of strings.

resolve(settings)

@spec resolve(map()) :: t()

Resolves feature flags from the merged TOML settings map.

Priority: environment variables > [features] TOML section > defaults (all :off).

validate(features)

@spec validate(t()) :: :ok | {:error, [String.t()]}

Validates that all feature flag values are recognised rollout states.

Returns :ok or {:error, [error_message]}.