> ## Documentation Index
> Fetch the complete documentation index at: https://docs.genesiscomputing.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Configuration Reference

> Every Genesis configuration setting: what it does, its type and default, and how to set it.

This page lists every Genesis configuration setting. It is generated from the same definitions
that **Config > Advanced Settings** shows, so the two always agree.

Settings for the Kubernetes objects Genesis runs in, such as the image, ingress, storage and
service account, are Helm values instead: see the
[Helm Chart Values Reference](https://docs.genesiscomputing.com/docs/deployments/Helm-Chart-Values-Reference.md).

## How to set a setting

Each setting has a dotted path, such as `server.instance_name`. You can set it in any of these
ways:

* **A Genesis config file.** A YAML file whose nesting follows the path. On Kubernetes, pass it
  with `--set-file genesisConfig.content=genesis-config.yaml`; elsewhere, point the
  `GENESIS_CONFIG_FILE` environment variable at it. For example:

  ```yaml theme={null}
  server:
    instance_name: "prod2"
  llm:
    active_provider: "litellm_bedrock"
  ```

* **Advanced Settings.** Admins can change most settings in **Config > Advanced Settings**. See
  [Advanced Settings](https://docs.genesiscomputing.com/docs/Setup/Advanced-Settings.md).

* **An override environment variable.** Each setting's override is `GENESIS__` followed by its
  path in upper case, with `__` in place of each dot: `server.instance_name` is
  `GENESIS__SERVER__INSTANCE_NAME`. An override wins over everything else and locks the setting
  in Advanced Settings. On Kubernetes, set it under `config.extraEnv`.

Some settings also read a legacy environment variable, listed below as **Environment default**.
It applies only while the setting has no stored value. For a secret setting the variable is
listed as **Startup environment variable** instead: Genesis copies its value into a stored secret
once, at startup, so changing the variable later does not change the secret. Change it in
Advanced Settings instead.

From highest to lowest, Genesis uses: the `GENESIS__` override, then a value stored from a config
file, Advanced Settings or the API, then the environment default, then the built-in default. See
[Configuration precedence](https://docs.genesiscomputing.com/docs/deployments/Genesis-Operations-Runbook.md#configuration-precedence).

**Secret settings** hold a reference to the secret rather than the secret itself:
`secret_<name>` for a secret stored in Genesis, `env_<VARIABLE>` for an environment variable,
`aws_<name>[#field]` for AWS Secrets Manager or `gcp_<name>[#field]` for Google Secret Manager.
A plain value is accepted and stored as a Genesis secret. See
[External Secrets](https://docs.genesiscomputing.com/docs/Setup/External-Secrets.md).

Settings marked **Genesis Desktop only** take effect only in Genesis Desktop.

## Server Identity & Environment

#### `server.instance_name`

This install's name within the client (e.g. "prod2"). Sent with the client name on everything this install reports to Genesis Computing.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__SERVER__INSTANCE_NAME`

#### `server.client_name`

Customer this install belongs to (e.g. "acme"). Sent with the instance name on everything this install reports to Genesis Computing. A licence's client name takes precedence. Set via GENESIS\_\_SERVER\_\_CLIENT\_NAME or Advanced Settings.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__SERVER__CLIENT_NAME`

#### `server.billing_environment`

Whether this install is production or non-production, for Genesis Credit billing. Non-prod is billed at a lower price per credit and must not serve production users or production data. Unset means prod. dev, test and staging are read as non-prod; any other value as prod. A licence that names an environment takes precedence. Set via GENESIS\_\_SERVER\_\_BILLING\_ENVIRONMENT, Helm identity.environment or Advanced Settings. Separate from server.environment, which does not affect billing.

* **Type:** `str`
* **Default:** `"prod"`
* **Options:** `prod`, `non-prod`
* **Override:** `GENESIS__SERVER__BILLING_ENVIRONMENT`

#### `server.debug`

Enable debug mode

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__SERVER__DEBUG`
* **Environment default:** `FASTAPI_DEBUG`

#### `server.laptop_mode`

Genesis runs on the signed-in person's own computer. Offers the browser sign-in connection modes (Snowflake and Databricks), which open the system browser on the machine running Genesis and cache the sign-in there. Leave off on any shared or hosted server.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__SERVER__LAPTOP_MODE`
* **Environment default:** `GENESIS_LAPTOP_MODE`

#### `server.environment`

Environment name (development, staging, production)

* **Type:** `str`
* **Default:** `"development"`
* **Override:** `GENESIS__SERVER__ENVIRONMENT`
* **Environment default:** `ENVIRONMENT`

#### `server.enable_periodic_summary`

Enable periodic summary logging

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__SERVER__ENABLE_PERIODIC_SUMMARY`
* **Environment default:** `ENABLE_PERIODIC_SUMMARY`

#### `server.slack_alerts_channel`

Slack channel name or ID for system alerts (e.g. scheduled job failures). Leave empty to disable Slack alerts.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__SERVER__SLACK_ALERTS_CHANNEL`

#### `server.slack_alert_sender_bot_id`

Bot ID whose distinct Slack identity posts targeted system alerts. Leave empty to disable targeted Slack alert activation.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__SERVER__SLACK_ALERT_SENDER_BOT_ID`

#### `server.session_warmup_stall_seconds`

GEN-2143: seconds startup will wait with NO forward progress in agent session warmup (no additional bot session completing) before promoting the server to degraded-but-ready and continuing warmup in the background. This is a STALL window, not a total-warmup cap: a healthy fleet that keeps completing bots never trips it regardless of size or network speed -- only a genuine hang (e.g. the embedded-Tailscale wedge where warmup blocks on absent egress) makes forward progress stop. Set to 0 to disable the watchdog and restore the original block-until-warmup-completes behavior.

* **Type:** `int`
* **Default:** `180`
* **Override:** `GENESIS__SERVER__SESSION_WARMUP_STALL_SECONDS`
* **Environment default:** `GENESIS_STARTUP_WARMUP_STALL_SECONDS`

## Genesis Desktop

#### `desktop.computer_use_enabled`

Allow Computer Use only in the local Genesis Desktop app, after the signed-in person selects approved apps in Settings. Off hides the agent tool and refuses direct calls without starting a driver or requesting native permissions.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__DESKTOP__COMPUTER_USE_ENABLED`
* **Genesis Desktop only**

#### `desktop.computer_use_approval`

Computer Use consent recorded by Desktop settings: the signed-in subject, principal and explicitly approved app bundle identifiers and names. Native permission state is never persisted here; it is read from the owned runtime.

* **Type:** `dict`
* **Default:** `{}`
* **Override:** `GENESIS__DESKTOP__COMPUTER_USE_APPROVAL`
* **Genesis Desktop only**

#### `desktop.auth0_domain`

Auth0 tenant Genesis Desktop signs its person in with (laptop mode only): the tenant whose tokens the live Try Me provisioner accepts. Public identifier, not a secret. A build for the test site sets genesis-trials.us.auth0.com (desktop/scripts/build-mac.sh GENESIS\_DESKTOP\_TARGET=test). Changing the tenant or the provisioner makes an installed app ask its person to sign in again.

* **Type:** `str`
* **Default:** `"dev-8fbfhxkny0ljn5er.us.auth0.com"`
* **Override:** `GENESIS__DESKTOP__AUTH0_DOMAIN`
* **Genesis Desktop only**

#### `desktop.auth0_client_id`

Client id of the public "Genesis Desktop" native application (PKCE, no secret) on that tenant. Its allowed callbacks are the provisioner's /desktop/callback/\<port> relay and [http://127.0.0.1](http://127.0.0.1) and [http://localhost](http://localhost) at /api/desktop/auth/callback, on ports 47080-47083.

* **Type:** `str`
* **Default:** `"jcVs31l3dROtdqLeCg2ZYuinS1wGF4Si"`
* **Override:** `GENESIS__DESKTOP__AUTH0_CLIENT_ID`
* **Genesis Desktop only**

#### `desktop.auth0_audience`

API audience requested with the sign-in, so the access token is accepted by the Try Me provisioner.

* **Type:** `str`
* **Default:** `"https://provisioner.genesis.app"`
* **Override:** `GENESIS__DESKTOP__AUTH0_AUDIENCE`
* **Genesis Desktop only**

#### `desktop.provisioner_base_url`

Try Me provisioner that activates a signed-in Genesis Desktop and may issue it a LiteLLM key for the default model: the live Try Me site. The Desktop shell builds take this default unless the build sets GENESIS\_PROVISIONER\_BASE\_URL (the test site: [https://genesis-provisioner-desktop-test.fly.dev](https://genesis-provisioner-desktop-test.fly.dev)).

* **Type:** `str`
* **Default:** `"https://try.genesiscomputing.io"`
* **Override:** `GENESIS__DESKTOP__PROVISIONER_BASE_URL`
* **Genesis Desktop only**

#### `desktop.callback_relay_url`

HTTPS page the identity provider returns to after sign-in, which forwards the code and state to this backend's loopback callback (the port is the last path segment, e.g. https\://\<provisioner>/desktop/callback/47080). An HTTPS callback lets Auth0 skip its consent screen for the first-party Genesis Desktop application. Empty: return straight to the loopback callback (the fallback). Defaults to the live Try Me site's relay.

* **Type:** `str`
* **Default:** `"https://try.genesiscomputing.io/desktop/callback"`
* **Override:** `GENESIS__DESKTOP__CALLBACK_RELAY_URL`
* **Genesis Desktop only**

#### `desktop.local_cli_enabled`

Administrator's switch for command mode: on Genesis Desktop (laptop mode, server.laptop\_mode), let agents run any bash command on this computer through the run\_local\_command tool, inside an OS sandbox (Anthropic sandbox-runtime). In the sandbox a command can read the person's files and system files, write only its working folder, and reach any internet host. Credential stores stay unreadable while desktop.file\_access\_block\_credentials is on, except the settings and sign-in of the aws, gh, az or git CLI the command runs. Plain reads (ls, cat, grep, git status, aws ... list-...) run at once; every other command, including any pipe, '&&' or redirect, waits for the person's approval in Action Review. Off: agents are not shown the tool and a call is refused. Checked live: flipping it takes effect on the next agent turn without a restart. Outside laptop mode the tool is never registered and this has no effect. Always on in Genesis Desktop, whatever is stored: shown locked there, and a change is refused.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__DESKTOP__LOCAL_CLI_ENABLED`
* **Genesis Desktop only**

#### `desktop.local_cli_srt_command`

Command line that starts Genesis's sandbox launcher (desktop/sandbox-runtime/genesis-srt.mjs, which runs Anthropic sandbox-runtime), e.g. "/path/to/node /path/to/desktop/sandbox-runtime/genesis-srt.mjs", for a developer checkout with that folder's packages installed (npm ci). Empty: the launcher the Genesis Desktop app ships, run on the Node.js runtime its browser tools install downloads. Used only when desktop.local\_cli\_enabled is on.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__DESKTOP__LOCAL_CLI_SRT_COMMAND`
* **Genesis Desktop only**

#### `desktop.local_cli_open_loopback_ports`

Ports on this computer (localhost: 127.0.0.1, ::1) that a command a person approved in run\_local\_command may connect to: local databases and dev servers (3000 web dev servers, 3306 MySQL, 5432 Postgres, 6379 Redis, 8000 and 8888 Python and Jupyter servers). Every other port on this computer stays closed to commands. Opening a port lets approved commands do whatever that service allows a local client without a password: a Postgres that trusts local connections, a Jupyter server or an older Redis lets them run programs outside the sandbox, so remove a port whose service you do not trust that far. Genesis ports are refused here, since a command that could call a Genesis backend whose endpoints are open could approve its own action cards: Genesis Desktop's 47080-47083, a backend's default 8080, a developer's local stacks (8081-8085, and the dashboard dev servers on 5173-5175 that forward to them) and the port this backend listens on. Checked on every command: a change applies to the next one, with no restart. Commands that run without approval and runs under a standing grant never reach this computer's ports. On Genesis Desktop, where every Genesis endpoint requires the launch secret or the MCP key, an approved command reaches every port instead, so it can use every local service (a kubectl proxy, a browser's debugging port, Ollama, Jupyter), including one listening on all addresses. This list applies instead while a GenesisApp is running that Genesis cannot confirm refuses callers without its key (one Genesis deployed to a local Docker container, or one with a server the guard does not cover), while another server listens on one of the Genesis ports above (a Genesis stack on another port is not detected), or while Docker's TCP API (2375, 2376; other ports are not detected) listens and Docker is not allowed for commands. It is decided as each command starts, and a running command keeps what it got until it ends, even if such an app starts meanwhile.

* **Type:** `list`
* **Default:** `[3000, 3306, 5432, 6379, 8000, 8888]`
* **Override:** `GENESIS__DESKTOP__LOCAL_CLI_OPEN_LOOPBACK_PORTS`
* **Genesis Desktop only**

#### `desktop.local_cli_background_max_seconds`

Longest a background command may run on Genesis Desktop, in seconds (default 7200, 2 hours). A command an agent runs with run\_local\_command(background=true) once the person approves it, or one the person sends to the background with `!`, keeps running after the chat moves on (a build, a test suite, a dev server) and is ended when it reaches this limit. An agent may ask for less, never more. Read when a run starts; a change applies to the next one.

* **Type:** `int`
* **Default:** `7200`
* **Override:** `GENESIS__DESKTOP__LOCAL_CLI_BACKGROUND_MAX_SECONDS`
* **Genesis Desktop only**

#### `desktop.local_cli_background_max_runs`

Most background commands one person may have running at once on Genesis Desktop (default 3). A start beyond it is refused until one ends or is stopped. 0 turns background commands off: commands then run only while the agent waits, up to 300 seconds. Read when a run starts.

* **Type:** `int`
* **Default:** `3`
* **Override:** `GENESIS__DESKTOP__LOCAL_CLI_BACKGROUND_MAX_RUNS`
* **Genesis Desktop only**

#### `desktop.local_cli_docker_enabled`

Lets a command a person approved in run\_local\_command use Docker on this computer. Docker is a permission of its own, not part of approving a command: a container the Docker daemon starts runs outside the sandbox, so it can mount and read any folder Docker Desktop shares (the whole home folder, credential stores and Genesis's own data among them) and reach Genesis on this computer through host.docker.internal. Off: approved commands cannot reach the Docker socket, and an agent whose command needed it is told this setting. Commands that run without approval and runs under a standing grant never get Docker. Checked on every command: a change applies to the next one, with no restart.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__DESKTOP__LOCAL_CLI_DOCKER_ENABLED`
* **Genesis Desktop only**

#### `desktop.file_access_block_credentials`

On Genesis Desktop (laptop mode, server.laptop\_mode), agents can list, read and search files anywhere on this computer through the local\_files tool, and write, delete or move them after the person approves. While this is on, folders and files that hold sign-ins and keys stay closed to them, because what an agent reads is sent to the AI model: \~/.ssh, \~/.aws, \~/.azure, \~/.gnupg, \~/.config/gcloud, \~/.config/gh, \~/.kube, \~/.docker, \~/.netrc, \~/.git-credentials, other CLI sign-ins (Databricks, Snowflake, dbt, npm, PyPI, Terraform, Cargo, Maven, Gradle, RubyGems, Vault, Oracle Cloud, 1Password, Claude Code, Codex), shell history, the macOS keychain and desktop keyring, browser profiles and cookies, .env and .envrc files, and Genesis's own database, logs and keys. Off: agents can open them too, except that a command an agent runs never reads Genesis's own data. Checked on every call. Outside laptop mode the tool is never registered and this has no effect.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__DESKTOP__FILE_ACCESS_BLOCK_CREDENTIALS`
* **Genesis Desktop only**

#### `desktop.dns_fallback_enabled`

On Genesis Desktop (laptop mode, server.laptop\_mode), when the computer's own DNS resolver fails for a host Genesis Desktop itself needs (the LiteLLM proxy in providers.litellm\_proxy.connection.base\_url and the Try Me provisioner in desktop.provisioner\_base\_url), look the name up directly at 1.1.1.1 and then 8.8.8.8 and connect to that address. The connection still uses the original hostname for TLS, so the certificate is verified against it. Answers are reused for their DNS TTL; private and local names are never looked up this way. One WARNING per outage: "system DNS failed for \<host>; using fallback resolver". Ignored outside laptop mode. Read at call time.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__DESKTOP__DNS_FALLBACK_ENABLED`
* **Genesis Desktop only**

#### `desktop.llm_stream_open_timeout_seconds`

On Genesis Desktop (laptop mode, server.laptop\_mode), how many seconds an LLM call may wait for the provider to start streaming before the attempt is abandoned and retried (llm.stream\_timeout\_max\_retries). A stalled Genesis AI reply is usually answered within seconds by the retry, so Desktop gives up sooner than a hosted or SPCS server, whose big models can legitimately take minutes to start and wait llm.call\_timeout\_seconds instead. An explicit llm.stream\_open\_timeout\_seconds still wins.

* **Type:** `float`
* **Default:** `60.0`
* **Minimum:** `1`
* **Override:** `GENESIS__DESKTOP__LLM_STREAM_OPEN_TIMEOUT_SECONDS`
* **Genesis Desktop only**

#### `desktop.llm_connection_error_retries`

On Genesis Desktop (laptop mode, server.laptop\_mode), retries for an LLM call that never reached the provider ("Connection error.": the connect or name resolution failed, for example while a home router's DNS flakes), in place of llm.connection\_error\_retries. Longer than a hosted server's: a home network's outages last about a minute. Used instead of llm.transient\_error\_retries when larger; 0 there still disables retries. Read at call time.

* **Type:** `int`
* **Default:** `11`
* **Minimum:** `0`
* **Maximum:** `20`
* **Override:** `GENESIS__DESKTOP__LLM_CONNECTION_ERROR_RETRIES`
* **Genesis Desktop only**

#### `desktop.llm_connection_retry_max_delay_seconds`

On Genesis Desktop, the upper bound in seconds for the wait between connection-failure retries, in place of llm.connection\_retry\_max\_delay\_seconds. With the defaults the waits between tries are 1, 2, 4 and 8 s, then 15 s seven times: 120 s in all, which rides out an outage of about two minutes when each try fails at once (DNS failure, refused connection); a try whose connect times out adds its connect timeout. Meanwhile the chat shows "Reconnecting to Genesis AI…" when the model is served by Genesis AI and "Reconnecting to the AI provider…" for any other provider, and Stop ends the wait. Read at call time.

* **Type:** `float`
* **Default:** `15.0`
* **Minimum:** `0`
* **Maximum:** `120`
* **Override:** `GENESIS__DESKTOP__LLM_CONNECTION_RETRY_MAX_DELAY_SECONDS`
* **Genesis Desktop only**

## Mission Value

#### `mission_value.manual_baselines`

Versioned per-mission manual duration baselines used by Mission Value. This value is managed through the dedicated Mission Value editor; while GENESIS\_\_MISSION\_VALUE\_\_MANUAL\_BASELINES is set, the editor refuses changes because the environment override has higher precedence.

* **Type:** `dict`
* **Default:** `{"schema_version": 1, "items": []}`
* **Override:** `GENESIS__MISSION_VALUE__MANUAL_BASELINES`

## Teams

#### `teams.enabled`

Global kill-switch for Microsoft Teams. When false it takes effect immediately, without a restart or a session rebuild: inbound Bot Framework activities are refused for every bot, and bots cannot send proactive Teams messages. No bot registers a Teams adapter either, regardless of its per-bot teams\_active flag, and any adapter registered before the switch was flipped is dropped the next time that bot's session is built. (The per-bot teams\_active flag is provisioning rather than an emergency control: turning it off removes that bot's adapter at its next session build, not on the next inbound request, because a per-request check would cost a database read per activity.) Two notes for operators migrating from the legacy GENESIS\_TEAMS\_ENABLED env var: (1) as a typed boolean this also accepts no/off/0, which the old string comparison ignored; (2) GENESIS\_TEAMS\_ENABLED is a default\_env\_var, so it only applies while this field has no explicitly-set value -- once set via the config UI/API the stored value wins. To force the switch regardless of stored config, use the override GENESIS\_\_TEAMS\_\_ENABLED=false.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__TEAMS__ENABLED`
* **Environment default:** `GENESIS_TEAMS_ENABLED`

#### `teams.relay_service_user`

Snowflake ingress principal confined to Teams relay endpoints; null disables relay confinement and the forwarded Bot Framework authorization header.

* **Type:** `str`
* **Default:** `null`
* **Override:** `GENESIS__TEAMS__RELAY_SERVICE_USER`

#### `teams.ingress_canary_enabled`

Expose the redacted Teams ingress characterization canary.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__TEAMS__INGRESS_CANARY_ENABLED`

#### `teams.allowed_service_url_hosts`

Additional HTTPS Bot Framework serviceUrl hosts allowed for inbound activities and outbound replies.

* **Type:** `list`
* **Default:** `[]`
* **Override:** `GENESIS__TEAMS__ALLOWED_SERVICE_URL_HOSTS`

## Slack

#### `slack.channel_monitors`

Channels an agent is responsible for watching. Each entry is a mapping: channel (id like C0123 or name like #occ-alerts), bot\_id (the responsible agent, which must be invited to the channel), trigger ("tagged", the default, starts work only when a new top-level message tags the agent; "every\_message" starts work for every new top-level message; "pattern" starts work for a message whose text, blocks or attachments match one of patterns, or that tags the agent; "watch" reads every new top-level message, and every reply in a thread the agent has not joined, and joins those a quick fast-model triage judges it can usefully help with or that speak to it, or that tag it), watch\_focus (optional, for "watch": what the agent cares about, e.g. "data pipeline failures and warehouse questions"), working\_reaction (optional true/false: whether the message that starts work shows the waiting reaction while the agent works; default true for every trigger, including "watch"), patterns (for "pattern": keywords matched as whole words, case insensitive, or /regular expressions/), exclude\_patterns (optional, same syntax: a matching message is skipped), action ("mission" starts a Mission from blueprint; "thread" opens a plain agent thread), blueprint (required for mission), allowed\_posters (optional list of Slack user, bot or app ids that may start work; empty means anyone, display names never match), run\_as (when allowed\_posters is set: "service", the default, runs the work as the non-admin Slack monitor service user; "system" runs it as the system identity, with administrator rights), ack\_emoji (optional reaction the agent adds the moment it picks a message up, e.g. "eyes") and enabled (default true). Replies in a thread the agent is working reach it as they arrive. Changes made through Settings, the API or an agent's manage\_slack\_channel\_monitors tool apply to running Slack connections at once; a hand-edited value applies when the agent's Slack connection next starts.

* **Type:** `list`
* **Default:** `[]`
* **Override:** `GENESIS__SLACK__CHANNEL_MONITORS`

#### `slack.watch_triage_max_per_minute`

For channel monitors with trigger "watch": at most this many messages per minute, per agent, are triaged with the fast model to decide whether the agent joins. Messages beyond it are skipped (the agent stays out) and the monitor's health shows it. 0 means no limit; a negative value is ignored (the default of 30 applies).

* **Type:** `int`
* **Default:** `30`
* **Override:** `GENESIS__SLACK__WATCH_TRIAGE_MAX_PER_MINUTE`

#### `slack.agent_to_agent_max_turns`

How many messages in a row from other bots (other agents included) one agent answers in a single Slack thread before it stops, so two agents tagging each other cannot keep going on their own. A message from a person in the thread starts the count again. 0 means no limit.

* **Type:** `int`
* **Default:** `10`
* **Override:** `GENESIS__SLACK__AGENT_TO_AGENT_MAX_TURNS`

#### `slack.home_team_id`

The Slack workspace (team) id, like T0123ABCD, whose members' Slack-verified email addresses are trusted to identify an existing Genesis user who has not linked their Slack account. Empty disables email matching. People from other workspaces (Slack Connect guests) are never matched by email.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__SLACK__HOME_TEAM_ID`

## Authentication

#### `auth.enabled`

Enable authentication

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__AUTH__ENABLED`
* **Environment default:** `AUTH_ENABLED`

#### `auth.provider`

Authentication provider

* **Type:** `str`
* **Default:** `"none"`
* **Options:** `none`, `auth0`, `oidc`, `snowflake`, `proxy`, `hosted`, `desktop`
* **Override:** `GENESIS__AUTH__PROVIDER`
* **Environment default:** `AUTH_PROVIDER`

#### `auth.issuer`

JWT issuer for token validation. Hosted requires urn:genesis:hosted-access:gateway:h1 with an independently pinned HTTPS JWKS URL; Auth0 uses an HTTPS issuer URL.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__AUTH__ISSUER`
* **Environment default:** `AUTH_ISSUER`

#### `auth.audience`

JWT audience for token validation. Required when provider is auth0; should match the API identifier in your Auth0 dashboard. Example: [https://genesis-api.example.com](https://genesis-api.example.com)

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__AUTH__AUDIENCE`
* **Environment default:** `AUTH_AUDIENCE`

#### `auth.jwks_url`

JWKS (JSON Web Key Set) URL for JWT verification. Required when provider is auth0. Example: [https://your-tenant.auth0.com/.well-known/jwks.json](https://your-tenant.auth0.com/.well-known/jwks.json)

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__AUTH__JWKS_URL`
* **Environment default:** `AUTH_JWKS_URL`

#### `auth.additional_issuers`

Additional accepted JWT issuers beyond the primary auth.issuer, keyed by a human-friendly name (the name is for readability only; matching is on the entry's issuer). Each value is an object \{issuer, jwks\_url, audience?, identity\_source?}. For an entry without login\_client\_id, audience defaults to auth.audience. identity\_source is 'sub' (default) or 'email' — 'email' resolves the Genesis user by the token's verified email (used by the OAuth-proxy identity broker) instead of by sub. An entry may also be offered as a second browser sign-in button, so e.g. Genesis staff can sign in through Genesis's Auth0 on an instance whose users sign in through the customer's Entra: set login\_client\_id (the IdP's browser/SPA app client id; its allowed callback and logout URL must be this deployment's origin), and optionally login\_label (button text, defaults to the entry name) and login\_scope (defaults to 'openid profile email offline\_access'; auth.scope is never reused for it). The dashboard sends that app's ID token, so such an entry always accepts aud = login\_client\_id, plus audience when set. An entry without jwks\_url is not offered as a button. Only offered when auth.provider is auth0 or oidc; the CLI and MCP OAuth logins keep using the primary IdP. Empty map rejects all non-primary issuers (original behavior). Example: \{"local-oauth-proxy": \{"issuer": "[https://proxy.example.com/identity](https://proxy.example.com/identity)", "jwks\_url": "[https://proxy.example.com/.well-known/jwks.json](https://proxy.example.com/.well-known/jwks.json)", "identity\_source": "email"}, "genesis-staff": \{"issuer": "https\://\<genesis-tenant>.us.auth0.com/", "jwks\_url": "https\://\<genesis-tenant>.us.auth0.com/.well-known/jwks.json", "login\_client\_id": "\<per-customer app client id>", "login\_label": "Genesis staff"}}.

* **Type:** `dict`
* **Default:** `{}`
* **Override:** `GENESIS__AUTH__ADDITIONAL_ISSUERS`

### auth.hosted

#### `auth.hosted.tenant_id`

Exact tenant binding required in every hosted identity assertion. Used only when auth.provider is hosted.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__AUTH__HOSTED__TENANT_ID`

#### `auth.hosted.installation_id`

Exact installation binding required in every hosted identity assertion. Used only when auth.provider is hosted.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__AUTH__HOSTED__INSTALLATION_ID`

#### `auth.hosted.assertion_contract`

Versioned hosted assertion contract. Hosted mode accepts only genesis-hosted-identity/v1.

* **Type:** `str`
* **Default:** `"genesis-hosted-identity/v1"`
* **Override:** `GENESIS__AUTH__HOSTED__ASSERTION_CONTRACT`

#### `auth.hosted.topology`

Proved hosted persistence topology. Hosted lifecycle mutations currently require legacy\_sqlite\_single\_writer.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__AUTH__HOSTED__TOPOLOGY`

#### `auth.client_id`

Auth0 client ID

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__AUTH__CLIENT_ID`
* **Environment default:** `AUTH0_CLIENT_ID`

#### `auth.cli_client_id`

OAuth client ID the terminal CLI login (`genesis login`) uses for its loopback+PKCE browser flow. A customer-hosted deployment may register a separate public/native OAuth app whose allowed callback is [http://localhost:PORT/callback](http://localhost:PORT/callback) for the CLI, rather than reuse the browser SPA client. Surfaced to the login command via /api/config/frontend as cli\_client\_id; when empty the CLI falls back to auth.client\_id.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__AUTH__CLI_CLIENT_ID`
* **Environment default:** `GENESIS_CLI_CLIENT_ID`

#### `auth.dynamic_client_registration`

Answer RFC 7591 dynamic client registration at POST /register, and advertise it as registration\_endpoint in the hosted MCP authorization-server metadata. Only takes effect when the MCP OAuth proxy is on (GENESIS\_OAUTH\_PROXY\_ENABLED) and auth.client\_id is set, because registration mints nothing: it hands back that already-public client id, which the proxy substitutes on /authorize and /oauth/token regardless of what a client presents. Required by MCP clients that refuse a server without it (Snowflake Cortex Code). Set false to refuse those clients.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__AUTH__DYNAMIC_CLIENT_REGISTRATION`

#### `auth.mcp_client_redirect_uris`

Non-loopback OAuth callbacks the hosted MCP redirect bridge will return an authorization code to, matched verbatim (no prefix matching). Only takes effect when the MCP OAuth proxy is on (GENESIS\_OAUTH\_PROXY\_ENABLED): /authorize then sends the upstream IdP this deployment's own \<public base>/oauth/callback, so Genesis — not the IdP — decides where a code lands, and anything that is neither loopback nor a built-in client callback must be named here. Loopback callbacks are accepted on any port, and the fixed callbacks of Claude ([https://claude.ai/api/mcp/auth\_callback](https://claude.ai/api/mcp/auth_callback), [https://claude.com/api/mcp/auth\_callback](https://claude.com/api/mcp/auth_callback)), Cursor (cursor://anysphere.cursor-mcp/oauth/callback, [https://www.cursor.com/agents/mcp/oauth/callback](https://www.cursor.com/agents/mcp/oauth/callback)) and VS Code ([https://vscode.dev/redirect](https://vscode.dev/redirect), [https://insiders.vscode.dev/redirect](https://insiders.vscode.dev/redirect)) are built in, so none of those need an entry. Add one only for another client that calls back to a real URL or its own app scheme, e.g. \["[https://console.anthropic.com/api/mcp/auth\_callback](https://console.anthropic.com/api/mcp/auth_callback)"]; javascript:, data:, file: and vbscript: callbacks are refused even when listed.

* **Type:** `list`
* **Default:** `[]`
* **Override:** `GENESIS__AUTH__MCP_CLIENT_REDIRECT_URIS`

#### `auth.allow_query_token`

Allow authentication token in URL query parameters. WARNING: security risk — tokens may be logged in server logs.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__AUTH__ALLOW_QUERY_TOKEN`
* **Environment default:** `AUTH_ALLOW_QUERY_TOKEN`

#### `auth.scope`

OAuth2/OIDC scopes to request (e.g., 'openid profile email')

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__AUTH__SCOPE`
* **Environment default:** `AUTH_SCOPE`

#### `auth.proxy_sign_out_url`

Sign-out endpoint of the auth proxy in front of this deployment, used only when provider is proxy. When set, the header shows Sign out and sends the browser here to end the proxy session. Either an absolute http(s) URL (e.g. [https://auth.example.com/oauth2/sign\_out](https://auth.example.com/oauth2/sign_out), optionally with ?rd=\<url> to return somewhere afterwards) or a path on this host starting with / (e.g. /oauth2/sign\_out). Any other value is ignored. Empty keeps Sign out hidden, since there is no app session to end behind a proxy.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__AUTH__PROXY_SIGN_OUT_URL`
* **Environment default:** `AUTH_PROXY_SIGN_OUT_URL`

#### `auth.headless_launch_run_as`

The person a Blueprint mission started with the internal service token (X-Genesis-Internal-Token) acts for when the start request names nobody in run\_as: a Genesis user id or email of a person who can sign in, e.g. the instance's owner. The mission is then started exactly as that person would start it from the GUI (it records them as requested\_by\_user, its thread is theirs, and Prover registration and connection opening act for them), and records that a service launched it on their behalf. Empty (the default) keeps a service launch with no run\_as as the system identity, which names nobody, so person-scoped Prover acts on that mission are refused. A value that is not a person who can sign in refuses every service launch that relies on it. Only the internal service token reads this; a person's or an agent's own credential always starts a mission as its own person.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__AUTH__HEADLESS_LAUNCH_RUN_AS`

#### `auth.databricks_app_test_service_principals`

Databricks App only, off while empty: the application (client) ids of workspace service principals that may sign in as ordinary NON-admin Genesis users, for automated test identities such as UAT runs. Each listed principal is verified with the workspace exactly like a person (its forwarded OAuth token must resolve, at SCIM Me, to that service principal), lands on a stable account (subject databricks-sp:\<application id>, a non-routable \<application id>@uat.genesis.invalid email), gets only the default roles for new users, never takes a Databricks App's first-admin seat and is never granted a role through group mapping. Unlisted service principals, personal access tokens and the App's own identity are refused whatever this list says, and outside a Databricks App it has no effect. Example: \["7a1b2c3d-0000-4000-8000-00000000c0de"].

* **Type:** `list`
* **Default:** `[]`
* **Override:** `GENESIS__AUTH__DATABRICKS_APP_TEST_SERVICE_PRINCIPALS`

#### `auth.group_role_mapping`

Admin-only. Maps external group names to Genesis roles at every sign-in, e.g. \{"genesis-admins": "admin"}: a member of a mapped group gets that role, and loses it on leaving the group (a person signing in to a Databricks App keeps admin while no other usable admin exists). The groups come from the sign-in: OIDC claims, proxy headers, or the workspace's own SCIM answer for a Databricks App user (listed test service principals never get roles this way). GENESIS\_GROUP\_ROLE\_MAPPING\_FILE or GENESIS\_GROUP\_ROLE\_MAPPING, when set, take precedence. Roles change at each user's next sign-in.

* **Type:** `dict`
* **Default:** `{}`
* **Override:** `GENESIS__AUTH__GROUP_ROLE_MAPPING`

## Okta Directory Sync

#### `okta_directory_sync.enabled`

Run the Okta directory sync on a schedule. The sync reads the users assigned to the Genesis app in Okta and creates, updates and deactivates Genesis users as SCIM push would, for a deployment Okta's cloud cannot reach. Roles come from the sign-in group-role mapping (GENESIS\_GROUP\_ROLE\_MAPPING\_FILE / GENESIS\_GROUP\_ROLE\_MAPPING), applied with each user's Okta group names. Off: the job stays paused; an administrator can still run a sync from the Users page once the connection settings are filled in. A change takes effect at the next restart (or resume the job from Pulse).

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__OKTA_DIRECTORY_SYNC__ENABLED`

#### `okta_directory_sync.interval_seconds`

Seconds between scheduled Okta directory syncs (default 12 hours). 0 schedules none. A change takes effect at the next restart.

* **Type:** `int`
* **Default:** `43200`
* **Minimum:** `0`
* **Override:** `GENESIS__OKTA_DIRECTORY_SYNC__INTERVAL_SECONDS`

#### `okta_directory_sync.org_url`

Base URL of the Okta org, such as [https://example.okta.com](https://example.okta.com) (or its custom domain), with no path. Must be https.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OKTA_DIRECTORY_SYNC__ORG_URL`

#### `okta_directory_sync.client_id`

Client ID of the Okta API service app Genesis authenticates as. The app uses public key / private key client authentication and needs the okta.users.read, okta.groups.read and okta.apps.read scopes plus a read-only administrator role; DPoP may stay required.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OKTA_DIRECTORY_SYNC__CLIENT_ID`

#### `okta_directory_sync.private_key`

PEM private key (RSA, or EC P-256) of the Okta API service app; its public key is registered on the app. Literal \n sequences from a single-line paste are accepted.

* **Type:** `str`
* **Override:** `GENESIS__OKTA_DIRECTORY_SYNC__PRIVATE_KEY`
* **Startup environment variable:** `OKTA_DIRECTORY_SYNC_PRIVATE_KEY`
* **Secret**

#### `okta_directory_sync.key_id`

Key ID (kid) of the service app's public key in Okta. Needed only when the app has more than one key.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OKTA_DIRECTORY_SYNC__KEY_ID`

#### `okta_directory_sync.app_id`

ID of the Genesis app in Okta (the app users sign in with). The users assigned to it, directly or through groups, are the users Genesis provisions.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OKTA_DIRECTORY_SYNC__APP_ID`

#### `okta_directory_sync.max_deactivation_percent`

Largest share of the provisioned users one sync may deactivate. A run that would deactivate more (and more than 5 users), or that finds no assigned users at all, deactivates nobody and reports why, until an administrator runs the sync with allow\_mass\_deactivation. Protects against a misconfigured app or an Okta outage looking like everyone left.

* **Type:** `int`
* **Default:** `20`
* **Minimum:** `0`
* **Maximum:** `100`
* **Override:** `GENESIS__OKTA_DIRECTORY_SYNC__MAX_DEACTIVATION_PERCENT`

## Documentation

#### `docs.use_internal_docs`

When true (default), in-app documentation links open the locally served offline docs export at /client-docs (no external network, intranet-safe) and the backend refuses new hosted-docs sessions. When false, links open the hosted Mintlify docs (docs.genesiscomputing.com) directly. Override/lock at runtime with GENESIS\_\_DOCS\_\_USE\_INTERNAL\_DOCS.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__DOCS__USE_INTERNAL_DOCS`

#### `docs.mintlify_jwt_private_key`

PKCS#8 Ed25519 private key used to sign short-lived Mintlify documentation session JWTs. This secret is resolved per hosted-docs request and is never exposed through frontend config.

* **Type:** `str`
* **Override:** `GENESIS__DOCS__MINTLIFY_JWT_PRIVATE_KEY`
* **Startup environment variable:** `MINTLIFY_JWT_PRIVATE_KEY`
* **Secret**

## Document Index

#### `document_index.stats_cache_ttl_seconds`

How long document-index statistics may remain cached between invalidations, in seconds.

* **Type:** `float`
* **Default:** `600`
* **Minimum:** `1`
* **Override:** `GENESIS__DOCUMENT_INDEX__STATS_CACHE_TTL_SECONDS`
* **Environment default:** `DOCUMENT_INDEX_STATS_CACHE_TTL_SECONDS`

## Team Wiki

#### `wiki.write_enabled`

Master gate for the wiki feature. When false, the entire wiki\_tools group is hidden from agents (no read, search, list, or write) so they cannot expose a half-working wiki. Also enables Path A (wiki\_write tool) and Path B (Librarian background extraction). Checked live: flipping takes effect without a restart — the tools stay registered, but tool schemas are filtered per turn and dispatch refuses while the flag is off.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__WIKI__WRITE_ENABLED`

#### `wiki.librarian_enabled`

Gate the Librarian's background extraction loop (per-tick conversation scanning + correction detection) independently of wiki.write\_enabled. Defaults false: background extraction is opt-in, so enabling wiki.write\_enabled gives on-demand and flow wiki\_write WITHOUT automatic conversation scraping until an operator turns this on. Checked live each tick: flipping takes effect without a restart. The env gates WIKI\_LIBRARIAN\_DISABLED / GENESIS\_RUN\_WIKI\_LIBRARIAN still hard-disable spawn independently.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__WIKI__LIBRARIAN_ENABLED`

#### `wiki.extractor_model`

LLM model the Librarian uses for background extraction and for reconciling new learnings, including those written by on-demand and flow wiki\_write (e.g. 'litellm\_proxy/bedrock-claude-sonnet-5-5'; pick from the active provider's models in the UI). The provider prefix must name the active LLM provider (llm.active\_provider): a value naming any other provider is refused when saved and is not called after a provider switch until it is changed. Needed when wiki.librarian\_enabled=true.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__WIKI__EXTRACTOR_MODEL`

#### `wiki.correction_classifier_enabled`

Run H2 LLM-based correction detector in the Librarian trigger loop. Drives LLM spend. Like extractor\_model, only runs when wiki.librarian\_enabled=true.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__WIKI__CORRECTION_CLASSIFIER_ENABLED`

#### `wiki.correction_classifier_model`

LLM model the H2 correction classifier uses to judge post-surface user replies (e.g. 'litellm\_proxy/gpt-5-mini'; pick from the active provider's models in the UI). Used ONLY by the H2 correction scan (wiki.correction\_classifier\_enabled); checked when the scan runs. The provider prefix must name the active LLM provider (llm.active\_provider): a value naming any other provider is refused when saved and is not called after a provider switch until it is changed. Must be a NON-Claude model — Claude/Anthropic values are rejected by the cross-family validation to prevent self-family bias. When set, this value wins over the WIKI\_CORRECTION\_CLASSIFIER\_MODEL env var; when empty, that env var is used, and with neither set the scan fails with an explicit error.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__WIKI__CORRECTION_CLASSIFIER_MODEL`

#### `wiki.correction_learning_write_enabled`

Write an auto-supersession learning when the H2 correction classifier returns a confident contradiction whose user reply states the corrected fact (CLI-1063). When false the classifier stays telemetry-only: wiki.correction events record the writer decision (outcome=skipped\_write\_disabled) but nothing is written. Checked live per verdict; flipping takes effect without a restart. Only reachable when wiki.write\_enabled, wiki.librarian\_enabled and wiki.correction\_classifier\_enabled are all on.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__WIKI__CORRECTION_LEARNING_WRITE_ENABLED`

#### `wiki.correction_write_min_confidence`

Minimum classifier confidence for the H2 correction writer to persist an auto-supersession learning. Stricter than the 0.70 telemetry threshold: verdicts in between still emit wiki.correction events with outcome=skipped\_below\_write\_threshold and are never written. Checked live per verdict.

* **Type:** `float`
* **Default:** `0.85`
* **Minimum:** `0.0`
* **Maximum:** `1.0`
* **Override:** `GENESIS__WIKI__CORRECTION_WRITE_MIN_CONFIDENCE`

#### `wiki.admin_tools_enabled`

Register the seven wiki\_admin\_\* operator inspection tools. NOTE: read at tool-registry load time; flipping requires server restart.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__WIKI__ADMIN_TOOLS_ENABLED`

#### `wiki.admin_trace_bodies_enabled`

Allow wiki\_admin\_trace\_detail to return raw prompt/response bodies. Set TRUE only on single-tenant operator deploys.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__WIKI__ADMIN_TRACE_BODIES_ENABLED`

#### `wiki.degradation_ranker_enabled`

Switch wiki preview ranker from 'newest wins' to rollup-driven composite. Requires backfilled rollups first.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__WIKI__DEGRADATION_RANKER_ENABLED`

## Security

#### `security.tool_auth_mode`

How the user-role and agent-role tool checks combine. 'union' allows a tool when either principal's role grants it; 'intersection' allows it only when both do. A value that is neither resolves to 'intersection'.

* **Type:** `str`
* **Default:** `"union"`
* **Options:** `union`, `intersection`
* **Override:** `GENESIS__SECURITY__TOOL_AUTH_MODE`
* **Environment default:** `SECURITY_TOOL_AUTH_MODE`

#### `security.force_double_key_on_connections`

Make every connection behave as if require\_double\_key were enabled for access and credential resolution, whatever each connection stores. Independent of security.tool\_auth\_mode, which governs tools rather than connections. Two capability checks are not affected, because they ask whether a connection can serve a call that has no user rather than whether a principal may use it: Databricks headless M2M embeddings and the Google Chat shared service-account route both still read only the connection's stored flag, and both already refuse a connection that sets it.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__SECURITY__FORCE_DOUBLE_KEY_ON_CONNECTIONS`
* **Environment default:** `SECURITY_FORCE_DOUBLE_KEY_ON_CONNECTIONS`

#### `security.code_isolation`

How code an agent runs with execute\_python\_code (and pip in its custom environments) is isolated when the server is not root and so cannot drop to the cortex\_sandbox user (a Databricks App, for example). 'off' keeps the existing behaviour: the code runs as the server's own user. 'confine' runs it under Linux Landlock and seccomp: it may write only its scratch directory, read only system and interpreter directories, the Genesis SDK and the bot repositories, and cannot read other processes, ptrace them, or reach /databricks or the storage directory; it also cannot signal the server process, its process group or PID 1 by pid (other same-user processes, such as the thread-service worker, stay signalable). Execution is refused when the kernel lacks Landlock. Files it creates are owner-only; a mode change is applied only when the owner keeps rwx and group and other gain at most execute (0o700, 0o711), any other mode change and every owner change succeed without effect, and extended attributes are refused. The loopback API is still reachable, so with proxy authentication also enable proxy token verification or restrict trusted proxy addresses. Not available to confined code: /dev/shm (multiprocessing queues and pools), /proc for its own subprocesses, and writes to bot repositories outside its scratch. The server and its worker processes (thread service, Slack, Iceberg) become non-dumpable at startup, so switch this on before start rather than at runtime. Root deployments always drop privileges and ignore this setting. A value that is neither resolves to 'confine'. Set it with the GENESIS\_\_SECURITY\_\_CODE\_ISOLATION override in deployment config so a stored value cannot switch it off.

* **Type:** `str`
* **Default:** `"off"`
* **Options:** `off`, `confine`
* **Override:** `GENESIS__SECURITY__CODE_ISOLATION`

#### `security.allow_unconfined_coding_agents`

Only matters when security.code\_isolation is 'confine' and the server is not root. The Claude Code, Codex and Cortex Code tools then refuse to start their CLIs (and a person resuming one of their sessions is refused too), because their CLIs cannot be confined: they run agent-driven shell as the server's own user, which can rewrite the server's Python environment or kubeconfig and so reach its credentials through the next process the server starts. Turning this on lets them run anyway, which is equivalent to running agent code unconfined; a warning is logged. Status, results and cancel stay available, so a session started earlier can still be stopped. Set it with the GENESIS\_\_SECURITY\_\_ALLOW\_UNCONFINED\_CODING\_AGENTS override in deployment config; setting that override to false locks it off against a stored value.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__SECURITY__ALLOW_UNCONFINED_CODING_AGENTS`

## RBAC

### rbac.default\_pat\_capability\_for\_new\_roles

#### `rbac.default_pat_capability_for_new_roles.databases`

Default value of the Databases PAT capability checkbox in the Create Role modal.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__RBAC__DEFAULT_PAT_CAPABILITY_FOR_NEW_ROLES__DATABASES`
* **Environment default:** `RBAC_DEFAULT_PAT_CAPABILITY_FOR_NEW_ROLES_DATABASES`

#### `rbac.default_pat_capability_for_new_roles.git`

Default value of the Git & Code PAT capability checkbox in the Create Role modal.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__RBAC__DEFAULT_PAT_CAPABILITY_FOR_NEW_ROLES__GIT`
* **Environment default:** `RBAC_DEFAULT_PAT_CAPABILITY_FOR_NEW_ROLES_GIT`

#### `rbac.default_pat_capability_for_new_roles.cloud`

Default value of the Cloud & Storage PAT capability checkbox in the Create Role modal.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__RBAC__DEFAULT_PAT_CAPABILITY_FOR_NEW_ROLES__CLOUD`
* **Environment default:** `RBAC_DEFAULT_PAT_CAPABILITY_FOR_NEW_ROLES_CLOUD`

#### `rbac.default_pat_capability_for_new_roles.pipelines`

Default value of the Data Pipelines PAT capability checkbox in the Create Role modal.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__RBAC__DEFAULT_PAT_CAPABILITY_FOR_NEW_ROLES__PIPELINES`
* **Environment default:** `RBAC_DEFAULT_PAT_CAPABILITY_FOR_NEW_ROLES_PIPELINES`

#### `rbac.default_pat_capability_for_new_roles.tools`

Default value of the Dev Tools PAT capability checkbox in the Create Role modal.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__RBAC__DEFAULT_PAT_CAPABILITY_FOR_NEW_ROLES__TOOLS`
* **Environment default:** `RBAC_DEFAULT_PAT_CAPABILITY_FOR_NEW_ROLES_TOOLS`

#### `rbac.default_roles`

Default roles assigned to new users on first login. Overridden by admin UI config when set. Unset, new users get admin and user, and every admin is asked to choose what new users get until one saves a list; set it explicitly (for example \["user"], or \[] for no roles) to keep new users off admin.

* **Type:** `list`
* **Default:** `["admin", "user"]`
* **Override:** `GENESIS__RBAC__DEFAULT_ROLES`
* **Environment default:** `RBAC_DEFAULT_ROLES`

## HTTP Layer

#### `http.enable_request_logging`

Enable HTTP request logging

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__HTTP__ENABLE_REQUEST_LOGGING`
* **Environment default:** `ENABLE_REQUEST_LOGGING`

#### `http.enable_request_guards`

Enable request rate limiting guards

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__HTTP__ENABLE_REQUEST_GUARDS`
* **Environment default:** `ENABLE_REQUEST_GUARDS`

#### `http.enable_asset_caching`

Enable static asset caching

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__HTTP__ENABLE_ASSET_CACHING`
* **Environment default:** `ENABLE_ASSET_CACHING`

### http.cors

#### `http.cors.level`

CORS security level

* **Type:** `str`
* **Default:** `"strict"`
* **Options:** `disabled`, `permissive`, `strict`
* **Override:** `GENESIS__HTTP__CORS__LEVEL`
* **Environment default:** `CORS_LEVEL`

#### `http.cors.extra_origins`

Additional allowed origins

* **Type:** `list`
* **Default:** `[]`
* **Override:** `GENESIS__HTTP__CORS__EXTRA_ORIGINS`
* **Environment default:** `EXTRA_HTTP_CORS_ORIGINS`

### http.rate\_limit

#### `http.rate_limit.enabled`

Enable in-memory IP-based rate limit middleware

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__HTTP__RATE_LIMIT__ENABLED`
* **Environment default:** `ENABLE_RATE_LIMIT`

#### `http.rate_limit.requests_per_minute`

Max non-read HTTP requests per IP over \~60s window

* **Type:** `int`
* **Default:** `1000`
* **Override:** `GENESIS__HTTP__RATE_LIMIT__REQUESTS_PER_MINUTE`
* **Environment default:** `REQUESTS_PER_MINUTE`

#### `http.rate_limit.burst_requests_per_10s`

Max non-read bursts over \~10s window

* **Type:** `int`
* **Default:** `200`
* **Override:** `GENESIS__HTTP__RATE_LIMIT__BURST_REQUESTS_PER_10S`
* **Environment default:** `BURST_REQUESTS_PER_10S`

#### `http.rate_limit.read_requests_per_minute`

Max read-only HTTP requests per IP over \~60s window before temporary read throttling

* **Type:** `int`
* **Default:** `3000`
* **Override:** `GENESIS__HTTP__RATE_LIMIT__READ_REQUESTS_PER_MINUTE`
* **Environment default:** `READ_REQUESTS_PER_MINUTE`

#### `http.rate_limit.read_burst_requests_per_10s`

Max read-only HTTP bursts over \~10s window before temporary read throttling

* **Type:** `int`
* **Default:** `600`
* **Override:** `GENESIS__HTTP__RATE_LIMIT__READ_BURST_REQUESTS_PER_10S`
* **Environment default:** `READ_BURST_REQUESTS_PER_10S`

#### `http.rate_limit.read_retry_after_seconds`

Retry-After value returned when read-only traffic is temporarily throttled

* **Type:** `int`
* **Default:** `5`
* **Override:** `GENESIS__HTTP__RATE_LIMIT__READ_RETRY_AFTER_SECONDS`
* **Environment default:** `READ_RETRY_AFTER_SECONDS`

#### `http.rate_limit.ban_seconds`

How long to soft-ban an offending IP for non-read traffic (seconds)

* **Type:** `int`
* **Default:** `15`
* **Override:** `GENESIS__HTTP__RATE_LIMIT__BAN_SECONDS`
* **Environment default:** `RATE_LIMIT_BAN_SECONDS`

#### `http.rate_limit.ws_connects_per_minute`

Max WebSocket connection attempts per IP over \~60s

* **Type:** `int`
* **Default:** `150`
* **Override:** `GENESIS__HTTP__RATE_LIMIT__WS_CONNECTS_PER_MINUTE`
* **Environment default:** `WS_CONNECTS_PER_MINUTE`

#### `http.rate_limit.trust_x_forwarded_for`

Use X-Forwarded-For when present (behind reverse proxy)

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__HTTP__RATE_LIMIT__TRUST_X_FORWARDED_FOR`
* **Environment default:** `TRUST_X_FORWARDED_FOR`

#### `http.rate_limit.enforce_on_api_only`

If true, only enforce on /api routes

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__HTTP__RATE_LIMIT__ENFORCE_ON_API_ONLY`
* **Environment default:** `RATE_LIMIT_API_ONLY`

#### `http.rate_limit.extra_ignore_path_prefixes`

Additional path prefixes excluded from rate limits (added to default: /api/health, /api/health/startup, /api/notifications/count)

* **Type:** `list`
* **Default:** `[]`
* **Override:** `GENESIS__HTTP__RATE_LIMIT__EXTRA_IGNORE_PATH_PREFIXES`

#### `http.rate_limit.extra_whitelist_ips`

Additional IPs exempt from rate limiting (added to default: 127.0.0.1, ::1, localhost)

* **Type:** `list`
* **Default:** `[]`
* **Override:** `GENESIS__HTTP__RATE_LIMIT__EXTRA_WHITELIST_IPS`
* **Environment default:** `RATE_LIMIT_WHITELIST_IPS`

#### `http.rate_limit.app_proxy_burst_per_10s`

Max per-app proxy/read requests over \~10s before quarantine (does not trigger global IP ban)

* **Type:** `int`
* **Default:** `200`
* **Override:** `GENESIS__HTTP__RATE_LIMIT__APP_PROXY_BURST_PER_10S`
* **Environment default:** `APP_PROXY_BURST_PER_10S`

#### `http.rate_limit.app_quarantine_seconds`

How long to quarantine a single app when its traffic exceeds the per-app burst threshold

* **Type:** `int`
* **Default:** `10`
* **Override:** `GENESIS__HTTP__RATE_LIMIT__APP_QUARANTINE_SECONDS`
* **Environment default:** `APP_QUARANTINE_SECONDS`

## Support

#### `support.include_server_log_in_bug_reports`

Include server-side logs inside bug report ZIP bundles exported by agents

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__SUPPORT__INCLUDE_SERVER_LOG_IN_BUG_REPORTS`

#### `support.bundle_max_bytes`

Size ceiling (bytes) for a support bundle. Thread file attachments that do not fit are omitted and listed in file\_manifest.json; diagnostics are never dropped. Default 15MB: a mail attachment is base64-encoded, so 15MB of ZIP costs \~20MB on the wire and still clears Gmail's 25MB inbound limit. 0 disables the budget; a negative or unparseable value falls back to the default.

* **Type:** `int`
* **Default:** `15000000`
* **Override:** `GENESIS__SUPPORT__BUNDLE_MAX_BYTES`
* **Environment default:** `SUPPORT_BUNDLE_MAX_BYTES`

### support.log\_shipping

#### `support.log_shipping.enabled`

Send everything this install writes to logs/app.log, every entry of every level (DEBUG, INFO, WARNING, ERROR, CRITICAL) with its traceback, secrets and email addresses removed, to Genesis Computing, so problems on the install are visible to support. A backlog (after an outage) is sent in full, including app.log's rotated copies written since the last send. Acts only in the Genesis image run under Docker (GENESIS\_DISTRIBUTION=docker) or the Genesis Helm chart (GENESIS\_DISTRIBUTION=helm): SPCS, other Kubernetes deployments, Genesis Desktop, control-plane-managed deployments and other containers never send. On by default for a new install; an install upgraded from a release before 1.19.100 keeps it off until someone sets true here or GENESIS\_\_SUPPORT\_\_LOG\_SHIPPING\_\_ENABLED=true. Set false (GENESIS\_\_SUPPORT\_\_LOG\_SHIPPING\_\_ENABLED=false) to stop; takes effect at the next send. What is logged while it is off is never sent, even once it is back on; a server started with it off counts as off from the end of its startup.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__SUPPORT__LOG_SHIPPING__ENABLED`

#### `support.log_shipping.interval_seconds`

How often the log entries are sent, in seconds. 0 or less turns sending off, and what is logged meanwhile is never sent. Read when the server starts.

* **Type:** `int`
* **Default:** `300`
* **Override:** `GENESIS__SUPPORT__LOG_SHIPPING__INTERVAL_SECONDS`

#### `support.log_shipping.receiver_base_url`

Where the log entries are sent: the Genesis Computing control-plane Receiver. Must be an http(s) URL; anything else stops sending.

* **Type:** `str`
* **Default:** `"https://enhancements.genesiscomputing.ai"`
* **Override:** `GENESIS__SUPPORT__LOG_SHIPPING__RECEIVER_BASE_URL`

## Datasets

#### `datasets.enabled`

Enable datasets fast data layer API (/api/datasets)

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__DATASETS__ENABLED`
* **Environment default:** `DATASETS_ENABLED`

#### `datasets.snapshot_keep_last`

Inactive snapshots kept per user dataset whose refresh policy sets no ttl\_seconds; older ones are deleted, durable copies included, by the post-refresh prune and the scheduled dataset cleanup. The active snapshot is never deleted, nor the newest one after a rollback made an older one active (it is one of the kept). A dataset's own ttl\_seconds replaces this default. 0 turns the default off.

* **Type:** `int`
* **Default:** `30`
* **Minimum:** `0`
* **Override:** `GENESIS__DATASETS__SNAPSHOT_KEEP_LAST`

#### `datasets.snapshot_max_age_days`

Days after which an inactive snapshot of a user dataset without ttl\_seconds is deleted, alongside snapshot\_keep\_last. The newest snapshot is always kept. 0 turns the age limit off.

* **Type:** `int`
* **Default:** `0`
* **Minimum:** `0`
* **Override:** `GENESIS__DATASETS__SNAPSHOT_MAX_AGE_DAYS`

## Sqlite Durability

#### `sqlite_durability.user_db_max_bytes`

Largest size, in bytes, a user SQLite database (SQLite connections and the agents' workspace database) may grow to while durable storage is on (Databricks Apps). Writes and tool changes past it are refused. Each such database is uploaded whole on checkpoints and tool changes, so this bounds that cost. Also bounds each dataset snapshot: a refresh building a larger one fails and the previous snapshot stays active. 0 disables the limit.

* **Type:** `int`
* **Default:** `1073741824`
* **Override:** `GENESIS__SQLITE_DURABILITY__USER_DB_MAX_BYTES`

## Storage Sweep

#### `storage_sweep.boot_budget_s`

Seconds the catch-all sweep may spend restoring undeclared state files at boot (Databricks Apps with GENESIS\_DURABLE\_BY\_DEFAULT). Files past it are restored by the following sweep passes, or on demand when Genesis reads them.

* **Type:** `int`
* **Default:** `60`
* **Minimum:** `0`
* **Override:** `GENESIS__STORAGE_SWEEP__BOOT_BUDGET_S`

#### `storage_sweep.walk_interval_s`

Seconds between two full walks of the state folders by the catch-all sweep: the longest a change Genesis was not told about may wait before it is kept.

* **Type:** `int`
* **Default:** `120`
* **Minimum:** `30`
* **Override:** `GENESIS__STORAGE_SWEEP__WALK_INTERVAL_S`

#### `storage_sweep.max_delete_fraction`

Largest share of a state folder's kept files one sweep pass may record as deleted. A pass deleting more (a wiped or mis-mounted folder looks like a mass delete) is refused and the folder stays degraded until an administrator confirms the deletes. This guard covers tombstones, not repository whiteouts; tracked working-tree deletions may replace kept edits without confirmation.

* **Type:** `float`
* **Default:** `0.2`
* **Minimum:** `0.0`
* **Maximum:** `1.0`
* **Override:** `GENESIS__STORAGE_SWEEP__MAX_DELETE_FRACTION`

#### `storage_sweep.max_file_bytes`

Largest file, in bytes, the catch-all sweep keeps; a larger one is recorded as too large (and reported), never silently dropped. At most 2 GiB.

* **Type:** `int`
* **Default:** `2147483648`
* **Minimum:** `1`
* **Maximum:** `2147483648`
* **Override:** `GENESIS__STORAGE_SWEEP__MAX_FILE_BYTES`

#### `storage_sweep.root_quota_bytes`

Most bytes the catch-all sweep keeps per state folder; files past it are recorded as over quota (and reported). 0 disables the quota.

* **Type:** `int`
* **Default:** `53687091200`
* **Minimum:** `0`
* **Override:** `GENESIS__STORAGE_SWEEP__ROOT_QUOTA_BYTES`

#### `storage_sweep.repository_quota_bytes`

Most bytes the catch-all sweep keeps per top-level folder under repos/ (one agent workspace or repository); files past it are recorded as over quota. 0 disables it.

* **Type:** `int`
* **Default:** `5368709120`
* **Minimum:** `0`
* **Override:** `GENESIS__STORAGE_SWEEP__REPOSITORY_QUOTA_BYTES`

## Disk Guard

#### `disk_guard.warn_free_bytes`

Free space, in bytes, on the disk holding Genesis's local state below which the server logs a warning every five minutes and the admin durability report flags the disk as low. On a Databricks App that disk is shared with the other Apps on the node, and nothing else warns before it fills.

* **Type:** `int`
* **Default:** `5368709120`
* **Minimum:** `0`
* **Override:** `GENESIS__DISK_GUARD__WARN_FREE_BYTES`

#### `disk_guard.reserve_free_bytes`

Free space, in bytes, that large writes must leave on the state disk. A download, chat upload, git clone, dataset refresh or Python environment build that would go below it is refused with a message saying so. With 0, only a write that does not fit at all is refused.

* **Type:** `int`
* **Default:** `2147483648`
* **Minimum:** `0`
* **Override:** `GENESIS__DISK_GUARD__RESERVE_FREE_BYTES`

#### `disk_guard.budget_bytes`

Most bytes Genesis's own state files may take on local disk, as the storage sweep measures them (Databricks Apps only); a large write that would pass it is refused. 0 (the default) sets no budget, leaving only the free-space reserve.

* **Type:** `int`
* **Default:** `0`
* **Minimum:** `0`
* **Override:** `GENESIS__DISK_GUARD__BUDGET_BYTES`

## GenesisApps / Microapps

#### `apps.datasets_enabled`

Enable GenesisApps dataset bindings + GENESIS\_APP\_TOKEN injection

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__APPS__DATASETS_ENABLED`
* **Environment default:** `APPS_DATASETS_ENABLED`, `MICROAPPS_DATASETS_ENABLED`

#### `apps.thumbnails_enabled`

Enable server-side app thumbnails in the Apps library UI

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__APPS__THUMBNAILS_ENABLED`

#### `apps.autostart_after_restart`

Start again, in the background once the server is back up, the GenesisApps that were running when it stopped (a pod roll, a container restart, an upgrade). Apps stopped by a user, by their idle timeout or maximum lifetime, or that crashed stay stopped (a versioned app whose running runtime crashed is started again). An app that fails to start again is left stopped with its error saying why. Off leaves every app stopped after a restart until someone starts it.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__APPS__AUTOSTART_AFTER_RESTART`

### apps.dependencies

#### `apps.dependencies.mode`

GenesisApps dependency install mode

* **Type:** `str`
* **Default:** `"online"`
* **Options:** `online`, `mirror`, `wheelhouse`, `disabled`
* **Override:** `GENESIS__APPS__DEPENDENCIES__MODE`
* **Environment default:** `APPS_DEPENDENCIES_MODE`, `MICROAPPS_DEPENDENCIES_MODE`

#### `apps.dependencies.index_url`

Primary package index URL used in mirror mode. Example: [https://pypi.company.example/simple](https://pypi.company.example/simple)

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__APPS__DEPENDENCIES__INDEX_URL`
* **Environment default:** `APPS_DEPENDENCIES_INDEX_URL`, `MICROAPPS_DEPENDENCIES_INDEX_URL`

#### `apps.dependencies.extra_index_urls`

Additional package index URLs used in mirror mode

* **Type:** `list`
* **Default:** `[]`
* **Override:** `GENESIS__APPS__DEPENDENCIES__EXTRA_INDEX_URLS`
* **Environment default:** `APPS_DEPENDENCIES_EXTRA_INDEX_URLS`, `MICROAPPS_DEPENDENCIES_EXTRA_INDEX_URLS`

#### `apps.dependencies.wheelhouse_path`

Local wheelhouse path used in wheelhouse mode. Example: /opt/genesis/wheelhouse

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__APPS__DEPENDENCIES__WHEELHOUSE_PATH`
* **Environment default:** `APPS_DEPENDENCIES_WHEELHOUSE_PATH`, `MICROAPPS_DEPENDENCIES_WHEELHOUSE_PATH`

#### `apps.dependencies.trusted_hosts`

Trusted hosts passed to pip in mirror mode

* **Type:** `list`
* **Default:** `[]`
* **Override:** `GENESIS__APPS__DEPENDENCIES__TRUSTED_HOSTS`
* **Environment default:** `APPS_DEPENDENCIES_TRUSTED_HOSTS`, `MICROAPPS_DEPENDENCIES_TRUSTED_HOSTS`

#### `apps.dependencies.use_system_site_packages`

Create app venv with --system-site-packages for compatibility deployments

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__APPS__DEPENDENCIES__USE_SYSTEM_SITE_PACKAGES`
* **Environment default:** `APPS_DEPENDENCIES_USE_SYSTEM_SITE_PACKAGES`, `MICROAPPS_DEPENDENCIES_USE_SYSTEM_SITE_PACKAGES`

#### `apps.dependencies.npm_registry_url`

mirror mode, Node.js (AppKit) GenesisApps: the npm registry npm installs from, e.g. an Artifactory or Nexus npm repository ([https://npm.company.example/](https://npm.company.example/)). A Databricks App deploy ships it in the project's .npmrc. Required in mirror mode for an AppKit app.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__APPS__DEPENDENCIES__NPM_REGISTRY_URL`
* **Environment default:** `APPS_DEPENDENCIES_NPM_REGISTRY_URL`

#### `apps.dependencies.npm_cafile`

mirror mode: a PEM CA bundle npm trusts for npm\_registry\_url (a private CA).

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__APPS__DEPENDENCIES__NPM_CAFILE`
* **Environment default:** `APPS_DEPENDENCIES_NPM_CAFILE`

#### `apps.dependencies.npm_strict_ssl`

mirror mode: whether npm verifies npm\_registry\_url's TLS certificate. Off only for a registry whose certificate cannot be verified (the npm counterpart of trusted\_hosts).

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__APPS__DEPENDENCIES__NPM_STRICT_SSL`
* **Environment default:** `APPS_DEPENDENCIES_NPM_STRICT_SSL`

#### `apps.dependencies.npm_offline_path`

wheelhouse (offline) mode, AppKit GenesisApps: an npm cache directory (as npm's --cache writes it) or a directory of packed .tgz packages, installed from with no registry. Empty uses the cache the Genesis image ships for the AppKit template (/opt/genesis/npm-cache).

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__APPS__DEPENDENCIES__NPM_OFFLINE_PATH`
* **Environment default:** `APPS_DEPENDENCIES_NPM_OFFLINE_PATH`

### apps.map\_tiles

#### `apps.map_tiles.mode`

Where the maps in GenesisApps (migrated Workshop apps) get their base-map tiles. The viewer's browser fetches the tiles; every map library is served by the app itself. osm: OpenStreetMap's public tiles (light use only, under the OpenStreetMap tile usage policy). mapbox: Mapbox styles with mapbox\_access\_token. custom: url\_template, e.g. an internal tile server for an air-gapped site. An app's workshop\_app\_config.json "map\_tiles" overrides this. Takes effect when an app (re)starts.

* **Type:** `str`
* **Default:** `"osm"`
* **Options:** `osm`, `mapbox`, `custom`
* **Override:** `GENESIS__APPS__MAP_TILES__MODE`

#### `apps.map_tiles.url_template`

custom mode: the XYZ tile URL template with \{z}, \{x} and \{y} (optionally \{s}), such as [https://tiles.example.com/\&#123;z\&#125;/\&#123;x\&#125;/\&#123;y\&#125;.png](https://tiles.example.com/\&#123;z\&#125;/\&#123;x\&#125;/\&#123;y\&#125;.png). Use https: the apps proxy allows https images only.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__APPS__MAP_TILES__URL_TEMPLATE`

#### `apps.map_tiles.url_template_dark`

custom mode: the template for maps on a dark basemap; empty uses url\_template.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__APPS__MAP_TILES__URL_TEMPLATE_DARK`

#### `apps.map_tiles.attribution`

custom mode: the credit shown on the map (HTML allowed), as the tile provider requires.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__APPS__MAP_TILES__ATTRIBUTION`

#### `apps.map_tiles.max_zoom`

custom mode: the deepest zoom level the tile server serves; 0 leaves Leaflet's default (18).

* **Type:** `int`
* **Default:** `0`
* **Minimum:** `0`
* **Maximum:** `24`
* **Override:** `GENESIS__APPS__MAP_TILES__MAX_ZOOM`

#### `apps.map_tiles.mapbox_style_light`

mapbox mode: the owner/style id of the style drawn under a light basemap.

* **Type:** `str`
* **Default:** `"mapbox/light-v11"`
* **Override:** `GENESIS__APPS__MAP_TILES__MAPBOX_STYLE_LIGHT`

#### `apps.map_tiles.mapbox_style_dark`

mapbox mode: the owner/style id of the style drawn under a dark basemap.

* **Type:** `str`
* **Default:** `"mapbox/dark-v11"`
* **Override:** `GENESIS__APPS__MAP_TILES__MAPBOX_STYLE_DARK`

#### `apps.map_tiles.mapbox_access_token`

mapbox mode: the customer's Mapbox access token. It is handed to each app at start and reaches the viewer's browser in tile requests, as every Mapbox web map's does, so use a public (pk.) token restricted to the app's URLs in the Mapbox account. A Databricks App reads it from a Databricks secret instead (DEPLOY option mapbox\_token\_secret).

* **Type:** `str`
* **Override:** `GENESIS__APPS__MAP_TILES__MAPBOX_ACCESS_TOKEN`
* **Startup environment variable:** `MAPBOX_ACCESS_TOKEN`
* **Secret**

## LLM

#### `llm.opus55_effort`

Reasoning effort for Claude Opus 5.5 requests on Anthropic and Bedrock. Empty leaves the provider default unchanged. A message reasoning\_effort overrides this deployment value; an empty message value explicitly requests the provider default. Other models retain existing behavior.

* **Type:** `str`
* **Default:** `""`
* **Options:** \`\`, `low`, `medium`, `high`, `xhigh`, `max`
* **Override:** `GENESIS__LLM__OPUS55_EFFORT`

#### `llm.active_provider`

Active LLM provider (references a providers.\* key)

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__LLM__ACTIVE_PROVIDER`
* **Environment default:** `ACTIVE_LLM_PROVIDER`

#### `llm.twin_scanner_model_tier`

Chat-model tier the Twin context-graph scanner uses for bulk description generation, forwarded to the Twin subprocess at boot and on live reconfig. 'fast' (the default) minimizes scan cost; 'main'/'frontier' trade cost for richer descriptions. Resolves against the active provider's tier assignments (fast->fast\_model, main->default\_chat, frontier->premier\_model) and falls back to the provider's main model when the chosen tier has no model assigned.

* **Type:** `str`
* **Default:** `"fast"`
* **Options:** `fast`, `main`, `frontier`
* **Override:** `GENESIS__LLM__TWIN_SCANNER_MODEL_TIER`

#### `llm.call_timeout_seconds`

Timeout for LLM API calls in seconds.

* **Type:** `int`
* **Default:** `300`
* **Override:** `GENESIS__LLM__CALL_TIMEOUT_SECONDS`
* **Environment default:** `LLM_CALL_TIMEOUT_SECONDS`

#### `llm.connection_error_retries`

Retries for an LLM call that never reached the provider ("Connection error.": the connect or name resolution failed, for example while a home router's DNS flakes). Used instead of llm.transient\_error\_retries when larger; 0 there still disables retries. Each retry opens a fresh connection. Read at call time. Genesis Desktop uses desktop.llm\_connection\_error\_retries instead.

* **Type:** `int`
* **Default:** `6`
* **Minimum:** `0`
* **Maximum:** `20`
* **Override:** `GENESIS__LLM__CONNECTION_ERROR_RETRIES`

#### `llm.connection_retry_max_delay_seconds`

Upper bound in seconds for the wait between connection-failure retries. With the defaults they wait 1, 2, 4, 8, 16 and 16 s, 47 s in all, which rides out an outage of about 45 s. Read at call time. Genesis Desktop uses desktop.llm\_connection\_retry\_max\_delay\_seconds instead.

* **Type:** `float`
* **Default:** `16.0`
* **Minimum:** `0`
* **Maximum:** `120`
* **Override:** `GENESIS__LLM__CONNECTION_RETRY_MAX_DELAY_SECONDS`

#### `llm.provider_preflight_ttl_seconds`

How long (seconds) a SUCCESSFUL model-provider preflight is reused. Every Prover seat (spec-author, Adjudicator, Consult, stimulus) checks that the configured provider answers before it creates a run or a thread, with one small model call (fast tier, a few output tokens). Within this window a burst of seat starts shares that one call. A FAILED preflight is reused for at most 10 seconds whatever this says, so a re-authenticated provider is seen almost at once. 0 probes on every seat start. A Cortex deployment is not probed: it is reported ready without a model call, so this check does not detect Cortex availability. The probe's tokens are recorded as a cost fact under the seat that triggered it. Bounded 0..600 so a provider that stopped answering is noticed within ten minutes at most. Read at call time by genesis\_bots/llm/provider\_preflight.py.

* **Type:** `int`
* **Default:** `60`
* **Minimum:** `0`
* **Maximum:** `600`
* **Override:** `GENESIS__LLM__PROVIDER_PREFLIGHT_TTL_SECONDS`

#### `llm.stream_read_timeout_seconds`

Idle-read timeout (seconds) for streaming LLM responses before the first chunk arrives. Raised from the historic 120s default because cold-cache providers (e.g. Bedrock with large prompt payloads) can legitimately take longer to start emitting tokens. Observed: a fresh cold prompt against Bedrock Claude Sonnet 4.6 with a \~187KB payload can exceed 300s per attempt and only succeed on retry after prior attempts warm the route, so the default is now 900s to give a single cold attempt a realistic chance to complete. Active streams (after the first chunk) are guarded separately by `llm.active_stream_idle_timeout_seconds`. Configured here so it can be tuned from the Advanced Config UI without redeploying.

* **Type:** `float`
* **Default:** `900.0`
* **Override:** `GENESIS__LLM__STREAM_READ_TIMEOUT_SECONDS`

#### `llm.active_stream_idle_timeout_seconds`

Idle timeout (seconds) between two consecutive chunks of an already open stream. This is the guard for a provider that started emitting and then went quiet mid-answer, whereas `llm.stream_read_timeout_seconds` only covers the pause before the first chunk arrives. When it fires the thread fails with LLM\_CHUNK\_TIMEOUT; it also bounds the per-call `request_timeout` and the Bedrock httpx read budget. Raise it for providers that think for long stretches mid-stream (large tool payloads, extended reasoning).

* **Type:** `float`
* **Default:** `900.0`
* **Override:** `GENESIS__LLM__ACTIVE_STREAM_IDLE_TIMEOUT_SECONDS`

#### `llm.stream_no_progress_timeout_seconds`

Maximum seconds an already-open stream may run without delivering any new output (text, reasoning or tool-call arguments) before the turn is ended with `provider_stream_stalled`. Distinct from `llm.active_stream_idle_timeout_seconds`, which measures the gap between two consecutive *chunks*: a provider that holds the stream open with content-free keepalives resets that timer forever while the answer never grows, so only this bound ends it. Measured from stream open, so it also covers a stream that never produces a first token; keep it at or above the cold-start budget a large prompt needs. Async streaming path only — the synchronous express lane cannot slice its per-chunk wait.

* **Type:** `float`
* **Default:** `900.0`
* **Override:** `GENESIS__LLM__STREAM_NO_PROGRESS_TIMEOUT_SECONDS`

#### `llm.stream_timeout_max_retries`

How many times a streaming LLM call is re-sent after `llm.stream_read_timeout_seconds` fires before the first chunk arrives. Each retry discards the partial output and starts a fresh attempt, so the longest a turn can sit in `running` with a frozen `last_activity` is `stream_read_timeout_seconds x (1 + this)` — 45 minutes at the defaults, past the estate\_char reconcile reaper's 2400 s. Lower it to bound that window; raise it for providers whose cold start is slow but transient. A stall (`provider_stream_stalled`) is never retried whatever this says.

* **Type:** `int`
* **Default:** `2`
* **Override:** `GENESIS__LLM__STREAM_TIMEOUT_MAX_RETRIES`

#### `llm.active_stream_timeout_max_retries`

How many times a streaming LLM call is re-sent after `llm.active_stream_idle_timeout_seconds` fires — the stream had started and then went quiet between chunks. Off by default: a provider that fell silent mid-answer usually does so again, and each retry spends the whole idle budget before the turn can fail. Raise it when mid-stream silence is a dropped connection worth re-opening.

* **Type:** `int`
* **Default:** `0`
* **Override:** `GENESIS__LLM__ACTIVE_STREAM_TIMEOUT_MAX_RETRIES`

#### `llm.proxy_universe_refresh_interval_seconds`

Minimum seconds between two re-discoveries of a live-discovery proxy's model list triggered by opening a model-picking screen. Those screens are served from the saved Model Universe, so this only bounds how often the proxy itself is polled to keep that snapshot current — lower it to pick up newly added proxy models sooner, raise it if the proxy is slow or rate-limited. 0 disables the throttle (every open re-discovers).

* **Type:** `int`
* **Default:** `300`
* **Override:** `GENESIS__LLM__PROXY_UNIVERSE_REFRESH_INTERVAL_SECONDS`

#### `llm.num_retries`

Number of retries for failed LLM API calls. Migrated providers (e.g. Azure via the LiteLLM strategy) may override this per-call — Azure pins num\_retries=0.

* **Type:** `int`
* **Default:** `3`
* **Override:** `GENESIS__LLM__NUM_RETRIES`
* **Environment default:** `LLM_NUM_RETRIES`

#### `llm.rate_limit_recovery_seconds`

Maximum elapsed seconds after the first rate-limit error during which a chat call through the LiteLLM adapter may start another retry. Waiting and failed attempts share this budget; an already-started request keeps its own timeout. 0 disables rate-limit recovery retries.

* **Type:** `int`
* **Default:** `120`
* **Minimum:** `0`
* **Maximum:** `600`
* **Override:** `GENESIS__LLM__RATE_LIMIT_RECOVERY_SECONDS`

#### `llm.max_iterations_per_message`

Hard limit on LLM calls per single user message. Prevents runaway loops. 0 = unlimited.

* **Type:** `int`
* **Default:** `1000`
* **Override:** `GENESIS__LLM__MAX_ITERATIONS_PER_MESSAGE`
* **Environment default:** `LLM_MAX_ITERATIONS_PER_MESSAGE`

#### `llm.pricing`

Per-model LLM price overrides — a mapping of model name to a rate object. Rates are USD per 1 million tokens. Model names are matched case-insensitively; provider prefixes (anthropic/, a Bedrock prefix, etc.) are tolerated via substring match. Each rate object may set any of: input, output, cache\_read, cache\_write — omitted fields fall back to the LiteLLM catalog. Takes precedence over all other pricing sources. Example: \{"claude-sonnet-4-6": \{"input": 2.40, "output": 12.00}}

* **Type:** `dict`
* **Default:** `{}`
* **Override:** `GENESIS__LLM__PRICING`

#### `llm.engine_overrides`

Per-provider engine override map. Keys are provider identifiers — canonical names or aliases (e.g. azureopenai or azure); values are engine names (litellm, cortex). Unknown keys or values, including the retired openai engine, are logged and ignored; routing falls back to the built-in provider->engine map without rewriting saved settings. Absent (default) means no overrides. Changing an override does not rebind cached assistant instances; restart the server after edits.

* **Type:** `dict`
* **Default:** `{}`
* **Override:** `GENESIS__LLM__ENGINE_OVERRIDES`

## Provider Credentials & Configuration

### providers.openai

#### `providers.openai.admission`

auto: sufficient parameters permit use; any other value refuses the provider

* **Type:** `str`
* **Default:** `"auto"`
* **Options:** `auto`, `deny`
* **Override:** `GENESIS__PROVIDERS__OPENAI__ADMISSION`
* **Environment default:** `OPENAI_ADMISSION`

### providers.openai.connection

#### `providers.openai.connection.api_key`

OpenAI API key

* **Type:** `str`
* **Override:** `GENESIS__PROVIDERS__OPENAI__CONNECTION__API_KEY`
* **Startup environment variable:** `OPENAI_API_KEY`
* **Secret**

#### `providers.openai.connection.base_url`

Custom base URL for OpenAI-compatible API

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__OPENAI__CONNECTION__BASE_URL`
* **Environment default:** `OPENAI_BASE_URL`, `OPENAI_API_BASE`

### providers.openai.settings

#### `providers.openai.settings.default_model_tier`

Default model tier for OpenAI

* **Type:** `str`
* **Default:** `"frontier"`
* **Options:** `frontier`, `main`, `fast`
* **Override:** `GENESIS__PROVIDERS__OPENAI__SETTINGS__DEFAULT_MODEL_TIER`

### providers.openai.models

#### `providers.openai.models.default_chat`

Default OpenAI chat model

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__OPENAI__MODELS__DEFAULT_CHAT`
* **Environment default:** `OPENAI_MODEL_NAME`, `OPENAI_DEFAULT_MODEL`

#### `providers.openai.models.fast_model`

Fast OpenAI model for lightweight tasks

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__OPENAI__MODELS__FAST_MODEL`
* **Environment default:** `OPENAI_FAST_MODEL_NAME`

#### `providers.openai.models.premier_model`

Premiere OpenAI model

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__OPENAI__MODELS__PREMIER_MODEL`
* **Environment default:** `OPENAI_PREMIER_MODEL`

#### `providers.openai.models.supervisor`

Supervisor model

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__OPENAI__MODELS__SUPERVISOR`
* **Environment default:** `OPENAI_MODEL_SUPERVISOR`

#### `providers.openai.models.harvester`

Harvester model

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__OPENAI__MODELS__HARVESTER`
* **Environment default:** `OPENAI_HARVESTER_MODEL`

#### `providers.openai.models.knowledge_server`

Knowledge-server model

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__OPENAI__MODELS__KNOWLEDGE_SERVER`
* **Environment default:** `OPENAI_KNOWLEDGE_MODEL`

#### `providers.openai.models.embedding_model`

Embedding model for OpenAI

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__OPENAI__MODELS__EMBEDDING_MODEL`
* **Environment default:** `OPENAI_EMBEDDING_MODEL`

### providers.openai.model\_selection\_mode

#### `providers.openai.model_selection_mode.default_chat`

Provenance of default\_chat (default=system, override=user, deferred\_default=system waiting for its new default)

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__OPENAI__MODEL_SELECTION_MODE__DEFAULT_CHAT`

#### `providers.openai.model_selection_mode.fast_model`

Provenance of fast\_model

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__OPENAI__MODEL_SELECTION_MODE__FAST_MODEL`

#### `providers.openai.model_selection_mode.premier_model`

Provenance of premier\_model

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__OPENAI__MODEL_SELECTION_MODE__PREMIER_MODEL`

#### `providers.openai.model_selection_mode.supervisor`

Provenance of supervisor

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__OPENAI__MODEL_SELECTION_MODE__SUPERVISOR`

#### `providers.openai.model_selection_mode.harvester`

Provenance of harvester

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__OPENAI__MODEL_SELECTION_MODE__HARVESTER`

#### `providers.openai.model_selection_mode.knowledge_server`

Provenance of knowledge\_server

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__OPENAI__MODEL_SELECTION_MODE__KNOWLEDGE_SERVER`

### providers.openai.model\_deferral

#### `providers.openai.model_deferral.default_chat`

Written by Genesis: why default\_chat waits for a new Genesis default (JSON: target, previous, last\_error, first\_deferred\_at, last\_probed\_at). Empty unless model\_selection\_mode.default\_chat is deferred\_default.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__OPENAI__MODEL_DEFERRAL__DEFAULT_CHAT`

#### `providers.openai.model_deferral.fast_model`

Written by Genesis: why fast\_model waits for a new Genesis default (JSON: target, previous, last\_error, first\_deferred\_at, last\_probed\_at). Empty unless model\_selection\_mode.fast\_model is deferred\_default.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__OPENAI__MODEL_DEFERRAL__FAST_MODEL`

#### `providers.openai.model_deferral.premier_model`

Written by Genesis: why premier\_model waits for a new Genesis default (JSON: target, previous, last\_error, first\_deferred\_at, last\_probed\_at). Empty unless model\_selection\_mode.premier\_model is deferred\_default.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__OPENAI__MODEL_DEFERRAL__PREMIER_MODEL`

#### `providers.openai.model_deferral.supervisor`

Written by Genesis: why supervisor waits for a new Genesis default (JSON: target, previous, last\_error, first\_deferred\_at, last\_probed\_at). Empty unless model\_selection\_mode.supervisor is deferred\_default.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__OPENAI__MODEL_DEFERRAL__SUPERVISOR`

#### `providers.openai.model_deferral.harvester`

Written by Genesis: why harvester waits for a new Genesis default (JSON: target, previous, last\_error, first\_deferred\_at, last\_probed\_at). Empty unless model\_selection\_mode.harvester is deferred\_default.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__OPENAI__MODEL_DEFERRAL__HARVESTER`

#### `providers.openai.model_deferral.knowledge_server`

Written by Genesis: why knowledge\_server waits for a new Genesis default (JSON: target, previous, last\_error, first\_deferred\_at, last\_probed\_at). Empty unless model\_selection\_mode.knowledge\_server is deferred\_default.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__OPENAI__MODEL_DEFERRAL__KNOWLEDGE_SERVER`

### providers.azureopenai

#### `providers.azureopenai.admission`

auto: sufficient parameters permit use; any other value refuses the provider

* **Type:** `str`
* **Default:** `"auto"`
* **Options:** `auto`, `deny`
* **Override:** `GENESIS__PROVIDERS__AZUREOPENAI__ADMISSION`
* **Environment default:** `AZURE_OPENAI_ADMISSION`

### providers.azureopenai.connection

#### `providers.azureopenai.connection.api_key`

Azure OpenAI API key

* **Type:** `str`
* **Override:** `GENESIS__PROVIDERS__AZUREOPENAI__CONNECTION__API_KEY`
* **Startup environment variable:** `AZURE_OPENAI_API_KEY`, `AZURE_API_KEY`
* **Secret**

#### `providers.azureopenai.connection.endpoint`

Azure OpenAI endpoint URL

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__AZUREOPENAI__CONNECTION__ENDPOINT`
* **Environment default:** `AZURE_OPENAI_API_ENDPOINT`, `AZURE_OPENAI_ENDPOINT`, `AZURE_API_BASE`

#### `providers.azureopenai.connection.endpoint_name`

Azure endpoint display label (EAI grouping; not a runtime endpoint URL)

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__AZUREOPENAI__CONNECTION__ENDPOINT_NAME`

#### `providers.azureopenai.connection.api_version`

Azure OpenAI API version

* **Type:** `str`
* **Default:** `"2025-04-01-preview"`
* **Override:** `GENESIS__PROVIDERS__AZUREOPENAI__CONNECTION__API_VERSION`
* **Environment default:** `AZURE_OPENAI_API_VERSION`

### providers.azureopenai.settings

#### `providers.azureopenai.settings.default_model_tier`

Default model tier for Azure OpenAI

* **Type:** `str`
* **Default:** `"frontier"`
* **Options:** `frontier`, `main`, `fast`
* **Override:** `GENESIS__PROVIDERS__AZUREOPENAI__SETTINGS__DEFAULT_MODEL_TIER`

#### `providers.azureopenai.settings.stream_fallback`

Fall back to a non-streaming retry when the first token does not arrive within the timeout (LiteLLM engine path).

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__PROVIDERS__AZUREOPENAI__SETTINGS__STREAM_FALLBACK`
* **Environment default:** `AZURE_OPENAI_STREAM_FALLBACK`

#### `providers.azureopenai.settings.stream_fallback_timeout`

Seconds to wait for the first streamed token before retrying non-streaming.

* **Type:** `float`
* **Default:** `8.0`
* **Override:** `GENESIS__PROVIDERS__AZUREOPENAI__SETTINGS__STREAM_FALLBACK_TIMEOUT`
* **Environment default:** `AZURE_OPENAI_STREAM_FALLBACK_TIMEOUT`

#### `providers.azureopenai.settings.deployment_base_models`

Maps an Azure deployment name (bare, no 'azure/' prefix) to the canonical OpenAI model it serves — e.g. \{"prod-deploy": "gpt-5.1"}. Used for capability lookup (reasoning\_effort support, gpt-5.4+ Responses-bridge guard) when the deployment name itself does not resolve in LiteLLM's model cost map.

* **Type:** `dict`
* **Default:** `{}`
* **Override:** `GENESIS__PROVIDERS__AZUREOPENAI__SETTINGS__DEPLOYMENT_BASE_MODELS`

### providers.azureopenai.models

#### `providers.azureopenai.models.default_chat`

Azure deployment name for chat model

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__AZUREOPENAI__MODELS__DEFAULT_CHAT`
* **Environment default:** `AZURE_OPENAI_MODEL_DEPLOYMENT_NAME`

#### `providers.azureopenai.models.fast_model`

Azure fast deployment

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__AZUREOPENAI__MODELS__FAST_MODEL`
* **Environment default:** `AZURE_OPENAI_FAST_MODEL_NAME`

#### `providers.azureopenai.models.premier_model`

Azure premiere deployment

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__AZUREOPENAI__MODELS__PREMIER_MODEL`
* **Environment default:** `AZURE_OPENAI_PREMIER_MODEL`

#### `providers.azureopenai.models.supervisor`

Azure supervisor deployment

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__AZUREOPENAI__MODELS__SUPERVISOR`
* **Environment default:** `AZURE_OPENAI_SUPERVISOR_MODEL`

#### `providers.azureopenai.models.harvester`

Azure harvester deployment

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__AZUREOPENAI__MODELS__HARVESTER`
* **Environment default:** `AZURE_OPENAI_HARVESTER_MODEL`

#### `providers.azureopenai.models.knowledge_server`

Azure knowledge-server deployment

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__AZUREOPENAI__MODELS__KNOWLEDGE_SERVER`
* **Environment default:** `AZURE_OPENAI_KNOWLEDGE_MODEL`

#### `providers.azureopenai.models.embedding_model`

Azure deployment name for embedding model

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__AZUREOPENAI__MODELS__EMBEDDING_MODEL`
* **Environment default:** `AZURE_OPENAI_EMBEDDING_DEPLOYMENT_NAME`

### providers.azureopenai.model\_selection\_mode

#### `providers.azureopenai.model_selection_mode.default_chat`

Provenance of default\_chat

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__AZUREOPENAI__MODEL_SELECTION_MODE__DEFAULT_CHAT`

#### `providers.azureopenai.model_selection_mode.fast_model`

Provenance of fast\_model

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__AZUREOPENAI__MODEL_SELECTION_MODE__FAST_MODEL`

#### `providers.azureopenai.model_selection_mode.premier_model`

Provenance of premier\_model

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__AZUREOPENAI__MODEL_SELECTION_MODE__PREMIER_MODEL`

#### `providers.azureopenai.model_selection_mode.supervisor`

Provenance of supervisor

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__AZUREOPENAI__MODEL_SELECTION_MODE__SUPERVISOR`

#### `providers.azureopenai.model_selection_mode.harvester`

Provenance of harvester

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__AZUREOPENAI__MODEL_SELECTION_MODE__HARVESTER`

#### `providers.azureopenai.model_selection_mode.knowledge_server`

Provenance of knowledge\_server

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__AZUREOPENAI__MODEL_SELECTION_MODE__KNOWLEDGE_SERVER`

### providers.cortex

#### `providers.cortex.admission`

auto: sufficient parameters permit use; any other value refuses the provider

* **Type:** `str`
* **Default:** `"auto"`
* **Options:** `auto`, `deny`
* **Override:** `GENESIS__PROVIDERS__CORTEX__ADMISSION`

### providers.cortex.connection

#### `providers.cortex.connection.auth_method`

Cortex public-REST auth method. connection (Genesis Desktop / laptop mode): every call takes the account and credentials from the Snowflake connection named by connection\_name (its Snowflake OAuth sign-in, key pair or PAT); nothing is copied here.

* **Type:** `str`
* **Default:** `""`
* **Options:** `pat`, `keypair`, `connection`
* **Override:** `GENESIS__PROVIDERS__CORTEX__CONNECTION__AUTH_METHOD`
* **Environment default:** `CORTEX_AUTH_METHOD`

#### `providers.cortex.connection.connection_name`

With auth\_method connection: the Snowflake connection (its name, without the snowflake. prefix) Cortex authenticates through.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__CORTEX__CONNECTION__CONNECTION_NAME`

#### `providers.cortex.connection.account_url`

Snowflake account host for Cortex REST base URL

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__CORTEX__CONNECTION__ACCOUNT_URL`
* **Environment default:** `CORTEX_ACCOUNT_HOST`, `CORTEX_ACCOUNT_URL`, `CORTEX_ACCOUNT_IDENTIFIER`

#### `providers.cortex.connection.base_url`

Cortex REST/OpenAI-compatible base URL

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__CORTEX__CONNECTION__BASE_URL`
* **Environment default:** `CORTEX_BASE_URL`

#### `providers.cortex.connection.snowflake_user`

Snowflake user (key-pair JWT and/or SQL-path embeddings)

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__CORTEX__CONNECTION__SNOWFLAKE_USER`
* **Environment default:** `CORTEX_SNOWFLAKE_USER`

### providers.cortex.connection.pat

#### `providers.cortex.connection.pat.api_key`

Snowflake PAT for Cortex REST API

* **Type:** `str`
* **Override:** `GENESIS__PROVIDERS__CORTEX__CONNECTION__PAT__API_KEY`
* **Startup environment variable:** `CORTEX_API_KEY`
* **Secret**

#### `providers.cortex.connection.pat.warehouse`

Snowflake warehouse for SQL-path Cortex embeddings

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__CORTEX__CONNECTION__PAT__WAREHOUSE`
* **Environment default:** `CORTEX_WAREHOUSE`

#### `providers.cortex.connection.pat.role`

Snowflake role for SQL-path Cortex embeddings

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__CORTEX__CONNECTION__PAT__ROLE`
* **Environment default:** `CORTEX_ROLE`

### providers.cortex.connection.keypair

#### `providers.cortex.connection.keypair.private_key`

PEM private key for Snowflake key-pair JWT auth

* **Type:** `str`
* **Override:** `GENESIS__PROVIDERS__CORTEX__CONNECTION__KEYPAIR__PRIVATE_KEY`
* **Startup environment variable:** `CORTEX_PRIVATE_KEY`
* **Secret**

#### `providers.cortex.connection.keypair.private_key_passphrase`

Passphrase for an encrypted Cortex private key

* **Type:** `str`
* **Override:** `GENESIS__PROVIDERS__CORTEX__CONNECTION__KEYPAIR__PRIVATE_KEY_PASSPHRASE`
* **Startup environment variable:** `CORTEX_PRIVATE_KEY_PASSPHRASE`
* **Secret**

#### `providers.cortex.connection.keypair.snowflake_account`

Snowflake account identifier for key-pair JWT (ORGID-ACCTID)

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__CORTEX__CONNECTION__KEYPAIR__SNOWFLAKE_ACCOUNT`
* **Environment default:** `CORTEX_KEYPAIR_ACCOUNT`

### providers.cortex.settings

#### `providers.cortex.settings.max_output_tokens`

Explicit flat cap on output tokens for Cortex API calls, applied to every model. null (default) = resolve limits per-model instead (Opus 5 / Opus 4.8 get the measured 64000 Cortex ceiling; other models keep conservative per-model caps). A non-null default here would be exported into CORTEX\_MAX\_OUTPUT\_TOKENS at startup and silently cap every model, so only set a value to deliberately override the per-model table.

* **Type:** `int`
* **Default:** `null`
* **Override:** `GENESIS__PROVIDERS__CORTEX__SETTINGS__MAX_OUTPUT_TOKENS`
* **Environment default:** `CORTEX_MAX_OUTPUT_TOKENS`

#### `providers.cortex.settings.embedding_method`

Cortex embedding path (sql requires pat + connection.snowflake\_user/warehouse/role)

* **Type:** `str`
* **Default:** `""`
* **Options:** `rest`, `sql`, `keypair`
* **Override:** `GENESIS__PROVIDERS__CORTEX__SETTINGS__EMBEDDING_METHOD`

#### `providers.cortex.settings.default_model_tier`

Default model tier for Cortex

* **Type:** `str`
* **Default:** `"frontier"`
* **Options:** `frontier`, `main`, `fast`
* **Override:** `GENESIS__PROVIDERS__CORTEX__SETTINGS__DEFAULT_MODEL_TIER`

### providers.cortex.models

#### `providers.cortex.models.default_chat`

Cortex default chat model

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__CORTEX__MODELS__DEFAULT_CHAT`
* **Environment default:** `CORTEX_MODEL`, `CORTEX_LLM_MODEL`

#### `providers.cortex.models.premier_model`

Cortex premiere model

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__CORTEX__MODELS__PREMIER_MODEL`
* **Environment default:** `CORTEX_PREMIERE_MODEL`

#### `providers.cortex.models.fast_model`

Cortex fast model for lightweight tasks

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__CORTEX__MODELS__FAST_MODEL`
* **Environment default:** `CORTEX_FAST_MODEL_NAME`

#### `providers.cortex.models.supervisor`

Cortex supervisor model

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__CORTEX__MODELS__SUPERVISOR`
* **Environment default:** `CORTEX_SUPERVISOR_MODEL`

#### `providers.cortex.models.harvester`

Cortex harvester model

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__CORTEX__MODELS__HARVESTER`

#### `providers.cortex.models.embedding_model`

Embedding model for Cortex

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__CORTEX__MODELS__EMBEDDING_MODEL`
* **Environment default:** `CORTEX_EMBEDDING_MODEL`

### providers.cortex.model\_selection\_mode

#### `providers.cortex.model_selection_mode.default_chat`

Provenance of default\_chat

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__CORTEX__MODEL_SELECTION_MODE__DEFAULT_CHAT`

#### `providers.cortex.model_selection_mode.fast_model`

Provenance of fast\_model

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__CORTEX__MODEL_SELECTION_MODE__FAST_MODEL`

#### `providers.cortex.model_selection_mode.premier_model`

Provenance of premier\_model

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__CORTEX__MODEL_SELECTION_MODE__PREMIER_MODEL`

#### `providers.cortex.model_selection_mode.supervisor`

Provenance of supervisor

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__CORTEX__MODEL_SELECTION_MODE__SUPERVISOR`

#### `providers.cortex.model_selection_mode.harvester`

Provenance of harvester

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__CORTEX__MODEL_SELECTION_MODE__HARVESTER`

### providers.cortex.model\_deferral

#### `providers.cortex.model_deferral.default_chat`

Written by Genesis: why default\_chat waits for a new Genesis default (JSON: target, previous, last\_error, first\_deferred\_at, last\_probed\_at). Empty unless model\_selection\_mode.default\_chat is deferred\_default.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__CORTEX__MODEL_DEFERRAL__DEFAULT_CHAT`

#### `providers.cortex.model_deferral.fast_model`

Written by Genesis: why fast\_model waits for a new Genesis default (JSON: target, previous, last\_error, first\_deferred\_at, last\_probed\_at). Empty unless model\_selection\_mode.fast\_model is deferred\_default.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__CORTEX__MODEL_DEFERRAL__FAST_MODEL`

#### `providers.cortex.model_deferral.premier_model`

Written by Genesis: why premier\_model waits for a new Genesis default (JSON: target, previous, last\_error, first\_deferred\_at, last\_probed\_at). Empty unless model\_selection\_mode.premier\_model is deferred\_default.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__CORTEX__MODEL_DEFERRAL__PREMIER_MODEL`

#### `providers.cortex.model_deferral.supervisor`

Written by Genesis: why supervisor waits for a new Genesis default (JSON: target, previous, last\_error, first\_deferred\_at, last\_probed\_at). Empty unless model\_selection\_mode.supervisor is deferred\_default.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__CORTEX__MODEL_DEFERRAL__SUPERVISOR`

#### `providers.cortex.model_deferral.harvester`

Written by Genesis: why harvester waits for a new Genesis default (JSON: target, previous, last\_error, first\_deferred\_at, last\_probed\_at). Empty unless model\_selection\_mode.harvester is deferred\_default.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__CORTEX__MODEL_DEFERRAL__HARVESTER`

### providers.databricks

#### `providers.databricks.admission`

auto: sufficient parameters permit use; any other value refuses the provider

* **Type:** `str`
* **Default:** `"auto"`
* **Options:** `auto`, `deny`
* **Override:** `GENESIS__PROVIDERS__DATABRICKS__ADMISSION`
* **Environment default:** `DATABRICKS_ADMISSION`

### providers.databricks.connection

#### `providers.databricks.connection.auth_mode`

Databricks auth mode. pat: the configured personal access token. oauth: the per-user OAuth token from connection.oauth.connection\_name (service-principal M2M only for no-user calls). service\_principal: every call, with or without a user, uses a client-credentials token minted for the service\_principal Databricks connection named by connection.oauth.m2m\_connection\_name, with that connection's OAuth scope (default all-apis); no PAT and no per-user grant. app\_identity: every call, with or without a user, uses a token minted for the Databricks App's own service principal from the App runtime's DATABRICKS\_HOST / DATABRICKS\_CLIENT\_ID / DATABRICKS\_CLIENT\_SECRET; fails if they are absent, never falling back to a PAT or user token. Only meaningful when Genesis runs as a Databricks App.

* **Type:** `str`
* **Default:** `"pat"`
* **Options:** `pat`, `oauth`, `service_principal`, `app_identity`
* **Override:** `GENESIS__PROVIDERS__DATABRICKS__CONNECTION__AUTH_MODE`

#### `providers.databricks.connection.base_url`

Databricks workspace URL

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__DATABRICKS__CONNECTION__BASE_URL`
* **Environment default:** `DATABRICKS_BASE_URL`, `DATABRICKS_HOST`

#### `providers.databricks.connection.endpoint_style`

Which Databricks API serves models. serving\_endpoints: Model Serving at \<workspace>/serving-endpoints, models named by endpoint. ai\_gateway: Unity AI Gateway model services at \<workspace>/ai-gateway/mlflow/v1 (OpenAI-compatible chat and embeddings), models named by their full \<catalog>.\<schema>.\<service> name; the gateway has no model listing, so model names are entered by hand.

* **Type:** `str`
* **Default:** `"serving_endpoints"`
* **Options:** `serving_endpoints`, `ai_gateway`
* **Override:** `GENESIS__PROVIDERS__DATABRICKS__CONNECTION__ENDPOINT_STYLE`

### providers.databricks.connection.pat

#### `providers.databricks.connection.pat.api_key`

Databricks API key

* **Type:** `str`
* **Override:** `GENESIS__PROVIDERS__DATABRICKS__CONNECTION__PAT__API_KEY`
* **Startup environment variable:** `DATABRICKS_API_KEY`, `DATABRICKS_TOKEN`
* **Secret**

### providers.databricks.connection.oauth

#### `providers.databricks.connection.oauth.connection_name`

Name of the Databricks connection providing the OAuth token

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__DATABRICKS__CONNECTION__OAUTH__CONNECTION_NAME`

#### `providers.databricks.connection.oauth.m2m_connection_name`

Name of a service\_principal Databricks connection. With auth\_mode service\_principal it serves every call; with auth\_mode oauth it serves only no-user aux calls (M2M client\_credentials fallback)

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__DATABRICKS__CONNECTION__OAUTH__M2M_CONNECTION_NAME`

### providers.databricks.settings

#### `providers.databricks.settings.stream_fallback`

Fall back to non-streaming when streaming times out

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__PROVIDERS__DATABRICKS__SETTINGS__STREAM_FALLBACK`
* **Environment default:** `DATABRICKS_STREAM_FALLBACK`

#### `providers.databricks.settings.stream_fallback_timeout`

Seconds before stream-to-non-stream fallback

* **Type:** `float`
* **Default:** `2.0`
* **Override:** `GENESIS__PROVIDERS__DATABRICKS__SETTINGS__STREAM_FALLBACK_TIMEOUT`
* **Environment default:** `DATABRICKS_STREAM_FALLBACK_TIMEOUT`

#### `providers.databricks.settings.stream_options_disabled`

Databricks does not support OpenAI stream\_options parameter

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__PROVIDERS__DATABRICKS__SETTINGS__STREAM_OPTIONS_DISABLED`
* **Environment default:** `OPENAI_STREAM_OPTIONS_NOT_SUPPORTED`

#### `providers.databricks.settings.default_model_tier`

Default model tier for Databricks

* **Type:** `str`
* **Default:** `"frontier"`
* **Options:** `frontier`, `main`, `fast`
* **Override:** `GENESIS__PROVIDERS__DATABRICKS__SETTINGS__DEFAULT_MODEL_TIER`

### providers.databricks.models

#### `providers.databricks.models.default_chat`

Default Databricks chat model

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__DATABRICKS__MODELS__DEFAULT_CHAT`
* **Environment default:** `DATABRICKS_MODEL_NAME`

#### `providers.databricks.models.fast_model`

Databricks fast model name

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__DATABRICKS__MODELS__FAST_MODEL`
* **Environment default:** `DATABRICKS_FAST_MODEL_NAME`

#### `providers.databricks.models.premier_model`

Databricks premiere model

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__DATABRICKS__MODELS__PREMIER_MODEL`
* **Environment default:** `DATABRICKS_PREMIER_MODEL`

#### `providers.databricks.models.supervisor`

Databricks supervisor model

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__DATABRICKS__MODELS__SUPERVISOR`
* **Environment default:** `DATABRICKS_SUPERVISOR_MODEL`

#### `providers.databricks.models.harvester`

Databricks harvester model

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__DATABRICKS__MODELS__HARVESTER`
* **Environment default:** `DATABRICKS_HARVESTER_MODEL`

#### `providers.databricks.models.knowledge_server`

Databricks knowledge model

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__DATABRICKS__MODELS__KNOWLEDGE_SERVER`
* **Environment default:** `DATABRICKS_KNOWLEDGE_MODEL`

#### `providers.databricks.models.embedding_model`

Embedding model for Databricks

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__DATABRICKS__MODELS__EMBEDDING_MODEL`
* **Environment default:** `DATABRICKS_EMBEDDING_MODEL`

### providers.databricks.model\_selection\_mode

#### `providers.databricks.model_selection_mode.default_chat`

Provenance of default\_chat

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__DATABRICKS__MODEL_SELECTION_MODE__DEFAULT_CHAT`

#### `providers.databricks.model_selection_mode.fast_model`

Provenance of fast\_model

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__DATABRICKS__MODEL_SELECTION_MODE__FAST_MODEL`

#### `providers.databricks.model_selection_mode.premier_model`

Provenance of premier\_model

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__DATABRICKS__MODEL_SELECTION_MODE__PREMIER_MODEL`

#### `providers.databricks.model_selection_mode.supervisor`

Provenance of supervisor

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__DATABRICKS__MODEL_SELECTION_MODE__SUPERVISOR`

#### `providers.databricks.model_selection_mode.harvester`

Provenance of harvester

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__DATABRICKS__MODEL_SELECTION_MODE__HARVESTER`

#### `providers.databricks.model_selection_mode.knowledge_server`

Provenance of knowledge\_server

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__DATABRICKS__MODEL_SELECTION_MODE__KNOWLEDGE_SERVER`

### providers.databricks.model\_deferral

#### `providers.databricks.model_deferral.default_chat`

Written by Genesis: why default\_chat waits for a new Genesis default (JSON: target, previous, last\_error, first\_deferred\_at, last\_probed\_at). Empty unless model\_selection\_mode.default\_chat is deferred\_default.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__DATABRICKS__MODEL_DEFERRAL__DEFAULT_CHAT`

#### `providers.databricks.model_deferral.fast_model`

Written by Genesis: why fast\_model waits for a new Genesis default (JSON: target, previous, last\_error, first\_deferred\_at, last\_probed\_at). Empty unless model\_selection\_mode.fast\_model is deferred\_default.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__DATABRICKS__MODEL_DEFERRAL__FAST_MODEL`

#### `providers.databricks.model_deferral.premier_model`

Written by Genesis: why premier\_model waits for a new Genesis default (JSON: target, previous, last\_error, first\_deferred\_at, last\_probed\_at). Empty unless model\_selection\_mode.premier\_model is deferred\_default.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__DATABRICKS__MODEL_DEFERRAL__PREMIER_MODEL`

#### `providers.databricks.model_deferral.supervisor`

Written by Genesis: why supervisor waits for a new Genesis default (JSON: target, previous, last\_error, first\_deferred\_at, last\_probed\_at). Empty unless model\_selection\_mode.supervisor is deferred\_default.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__DATABRICKS__MODEL_DEFERRAL__SUPERVISOR`

#### `providers.databricks.model_deferral.harvester`

Written by Genesis: why harvester waits for a new Genesis default (JSON: target, previous, last\_error, first\_deferred\_at, last\_probed\_at). Empty unless model\_selection\_mode.harvester is deferred\_default.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__DATABRICKS__MODEL_DEFERRAL__HARVESTER`

#### `providers.databricks.model_deferral.knowledge_server`

Written by Genesis: why knowledge\_server waits for a new Genesis default (JSON: target, previous, last\_error, first\_deferred\_at, last\_probed\_at). Empty unless model\_selection\_mode.knowledge\_server is deferred\_default.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__DATABRICKS__MODEL_DEFERRAL__KNOWLEDGE_SERVER`

### providers.litellm\_anthropic

#### `providers.litellm_anthropic.admission`

auto: sufficient parameters permit use; any other value refuses the provider

* **Type:** `str`
* **Default:** `"auto"`
* **Options:** `auto`, `deny`
* **Override:** `GENESIS__PROVIDERS__LITELLM_ANTHROPIC__ADMISSION`
* **Environment default:** `ANTHROPIC_ADMISSION`

### providers.litellm\_anthropic.connection

#### `providers.litellm_anthropic.connection.api_key`

Anthropic API key

* **Type:** `str`
* **Override:** `GENESIS__PROVIDERS__LITELLM_ANTHROPIC__CONNECTION__API_KEY`
* **Startup environment variable:** `ANTHROPIC_API_KEY`
* **Secret**

### providers.litellm\_anthropic.settings

#### `providers.litellm_anthropic.settings.cache`

Enable prompt caching for Anthropic

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__PROVIDERS__LITELLM_ANTHROPIC__SETTINGS__CACHE`
* **Environment default:** `ANTHROPIC_CACHE`

#### `providers.litellm_anthropic.settings.cache_checkpoint_mode`

Cache only the system prompt and checkpoint markers; false reverts to legacy positional caching

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__PROVIDERS__LITELLM_ANTHROPIC__SETTINGS__CACHE_CHECKPOINT_MODE`
* **Environment default:** `ANTHROPIC_CACHE_CHECKPOINT_MODE`

#### `providers.litellm_anthropic.settings.cache_checkpoint_rolling_anchor`

In checkpoint mode, anchor the deep cache breakpoint on stable history instead of the latest user message

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__PROVIDERS__LITELLM_ANTHROPIC__SETTINGS__CACHE_CHECKPOINT_ROLLING_ANCHOR`
* **Environment default:** `ANTHROPIC_CACHE_CHECKPOINT_ROLLING_ANCHOR`

#### `providers.litellm_anthropic.settings.cache_proxy_heuristic`

Add Anthropic cache markers for Claude-named models whose caching support cannot be confirmed (proxy aliases)

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__PROVIDERS__LITELLM_ANTHROPIC__SETTINGS__CACHE_PROXY_HEURISTIC`
* **Environment default:** `ANTHROPIC_CACHE_PROXY_HEURISTIC`

#### `providers.litellm_anthropic.settings.default_model_tier`

Default model tier for Anthropic

* **Type:** `str`
* **Default:** `"frontier"`
* **Options:** `frontier`, `main`, `fast`
* **Override:** `GENESIS__PROVIDERS__LITELLM_ANTHROPIC__SETTINGS__DEFAULT_MODEL_TIER`

### providers.litellm\_anthropic.models

#### `providers.litellm_anthropic.models.default_chat`

Default Anthropic chat model

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_ANTHROPIC__MODELS__DEFAULT_CHAT`
* **Environment default:** `ANTHROPIC_MODEL_NAME`, `ANTHROPIC_MODEL`

#### `providers.litellm_anthropic.models.fast_model`

Anthropic fast model name

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_ANTHROPIC__MODELS__FAST_MODEL`
* **Environment default:** `ANTHROPIC_FAST_MODEL_NAME`

#### `providers.litellm_anthropic.models.premier_model`

Anthropic premiere model

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_ANTHROPIC__MODELS__PREMIER_MODEL`
* **Environment default:** `ANTHROPIC_PREMIER_MODEL`

### providers.litellm\_anthropic.model\_selection\_mode

#### `providers.litellm_anthropic.model_selection_mode.default_chat`

Provenance of default\_chat

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__LITELLM_ANTHROPIC__MODEL_SELECTION_MODE__DEFAULT_CHAT`

#### `providers.litellm_anthropic.model_selection_mode.fast_model`

Provenance of fast\_model

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__LITELLM_ANTHROPIC__MODEL_SELECTION_MODE__FAST_MODEL`

#### `providers.litellm_anthropic.model_selection_mode.premier_model`

Provenance of premier\_model

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__LITELLM_ANTHROPIC__MODEL_SELECTION_MODE__PREMIER_MODEL`

### providers.litellm\_anthropic.model\_deferral

#### `providers.litellm_anthropic.model_deferral.default_chat`

Written by Genesis: why default\_chat waits for a new Genesis default (JSON: target, previous, last\_error, first\_deferred\_at, last\_probed\_at). Empty unless model\_selection\_mode.default\_chat is deferred\_default.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_ANTHROPIC__MODEL_DEFERRAL__DEFAULT_CHAT`

#### `providers.litellm_anthropic.model_deferral.fast_model`

Written by Genesis: why fast\_model waits for a new Genesis default (JSON: target, previous, last\_error, first\_deferred\_at, last\_probed\_at). Empty unless model\_selection\_mode.fast\_model is deferred\_default.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_ANTHROPIC__MODEL_DEFERRAL__FAST_MODEL`

#### `providers.litellm_anthropic.model_deferral.premier_model`

Written by Genesis: why premier\_model waits for a new Genesis default (JSON: target, previous, last\_error, first\_deferred\_at, last\_probed\_at). Empty unless model\_selection\_mode.premier\_model is deferred\_default.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_ANTHROPIC__MODEL_DEFERRAL__PREMIER_MODEL`

### providers.litellm\_bedrock

#### `providers.litellm_bedrock.admission`

auto: sufficient parameters permit use; any other value refuses the provider

* **Type:** `str`
* **Default:** `"auto"`
* **Options:** `auto`, `deny`
* **Override:** `GENESIS__PROVIDERS__LITELLM_BEDROCK__ADMISSION`
* **Environment default:** `BEDROCK_ADMISSION`

### providers.litellm\_bedrock.connection

#### `providers.litellm_bedrock.connection.auth_mode`

Bedrock auth mode (api\_key=bearer token; iam\_role=boto3/IRSA/IMDS automatic, no stored creds)

* **Type:** `str`
* **Default:** `"api_key"`
* **Options:** `api_key`, `iam_role`
* **Override:** `GENESIS__PROVIDERS__LITELLM_BEDROCK__CONNECTION__AUTH_MODE`
* **Environment default:** `BEDROCK_AUTH_MODE`

#### `providers.litellm_bedrock.connection.endpoint_mode`

Bedrock endpoint mode: 'default' uses the standard regional Bedrock endpoint (needs aws\_region); 'custom' targets an enterprise proxy URL (needs custom\_endpoint.url).

* **Type:** `str`
* **Default:** `"default"`
* **Options:** `default`, `custom`
* **Override:** `GENESIS__PROVIDERS__LITELLM_BEDROCK__CONNECTION__ENDPOINT_MODE`
* **Environment default:** `BEDROCK_ENDPOINT_MODE`

#### `providers.litellm_bedrock.connection.aws_account_id`

AWS account ID used for Bedrock ARN formation. Optional: the chat runtime resolves models by short-form inference-profile id, and only the invoke-route connection test uses this value.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_BEDROCK__CONNECTION__AWS_ACCOUNT_ID`
* **Environment default:** `AWS_ACCOUNT_ID`

### providers.litellm\_bedrock.connection.api\_key

#### `providers.litellm_bedrock.connection.api_key.aws_bearer_token`

AWS bearer token for Bedrock

* **Type:** `str`
* **Override:** `GENESIS__PROVIDERS__LITELLM_BEDROCK__CONNECTION__API_KEY__AWS_BEARER_TOKEN`
* **Startup environment variable:** `AWS_BEARER_TOKEN_BEDROCK`
* **Secret**

### providers.litellm\_bedrock.connection.default\_endpoint

#### `providers.litellm_bedrock.connection.default_endpoint.aws_region`

AWS region for Bedrock. The deployment environment is read once per process; AppConfig keeps the input in memory across runtime projection and reloads. Explicit stored values, including an empty value, take precedence.

* **Type:** `str`
* **Default:** `"us-east-1"`
* **Override:** `GENESIS__PROVIDERS__LITELLM_BEDROCK__CONNECTION__DEFAULT_ENDPOINT__AWS_REGION`
* **Environment default:** `AWS_BEDROCK_REGION`

### providers.litellm\_bedrock.connection.custom\_endpoint

#### `providers.litellm_bedrock.connection.custom_endpoint.url`

Custom Bedrock runtime endpoint URL (enterprise proxy). The deployment environment is read once per process; AppConfig keeps the input in memory across runtime projection and reloads. Explicit stored values, including an empty value, take precedence.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_BEDROCK__CONNECTION__CUSTOM_ENDPOINT__URL`
* **Environment default:** `AWS_BEDROCK_RUNTIME_ENDPOINT`

#### `providers.litellm_bedrock.connection.custom_endpoint.auth_header`

Auth header NAME for the custom endpoint (e.g. bearer / x-api-key). The deployment environment is read once per process; AppConfig keeps the input in memory across runtime projection and reloads. Explicit stored values, including an empty value, take precedence.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_BEDROCK__CONNECTION__CUSTOM_ENDPOINT__AUTH_HEADER`
* **Environment default:** `AWS_BEDROCK_AUTH_HEADER`

### providers.litellm\_bedrock.settings

#### `providers.litellm_bedrock.settings.chat_route_mode`

Selects the Bedrock chat route used for LiteLLM chat models. Affects Bedrock chat routing only; embeddings and provider credentials are unchanged.

* **Type:** `str`
* **Default:** `"invoke"`
* **Options:** `invoke`, `converse`
* **Override:** `GENESIS__PROVIDERS__LITELLM_BEDROCK__SETTINGS__CHAT_ROUTE_MODE`

#### `providers.litellm_bedrock.settings.strip_regional_prefix`

Strip regional prefix (us., eu., apac., global.) from model IDs before sending to the proxy. Enable if your proxy expects plain model IDs like anthropic.claude-sonnet-4-6.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__PROVIDERS__LITELLM_BEDROCK__SETTINGS__STRIP_REGIONAL_PREFIX`

#### `providers.litellm_bedrock.settings.fake_stream`

Use non-streaming /converse endpoint for streaming requests. Enable if proxy rejects /converse-stream.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__PROVIDERS__LITELLM_BEDROCK__SETTINGS__FAKE_STREAM`

#### `providers.litellm_bedrock.settings.extra_headers`

Additional HTTP headers as a JSON object sent with every request to the custom endpoint. Example: \{"anthropic-version": "bedrock-2023-05-31", "x-tenant-id": "org1"}

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_BEDROCK__SETTINGS__EXTRA_HEADERS`

#### `providers.litellm_bedrock.settings.verify_ssl`

Verify TLS certificates for custom endpoint. Set false for self-signed or corporate CA certs.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__PROVIDERS__LITELLM_BEDROCK__SETTINGS__VERIFY_SSL`

#### `providers.litellm_bedrock.settings.default_model_tier`

Default model tier for Bedrock

* **Type:** `str`
* **Default:** `"frontier"`
* **Options:** `frontier`, `main`, `fast`
* **Override:** `GENESIS__PROVIDERS__LITELLM_BEDROCK__SETTINGS__DEFAULT_MODEL_TIER`

### providers.litellm\_bedrock.models

#### `providers.litellm_bedrock.models.default_chat`

Default Bedrock chat model

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_BEDROCK__MODELS__DEFAULT_CHAT`
* **Environment default:** `BEDROCK_MODEL_NAME`

#### `providers.litellm_bedrock.models.fast_model`

Bedrock fast model name

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_BEDROCK__MODELS__FAST_MODEL`
* **Environment default:** `BEDROCK_FAST_MODEL_NAME`

#### `providers.litellm_bedrock.models.premier_model`

Bedrock premiere model

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_BEDROCK__MODELS__PREMIER_MODEL`
* **Environment default:** `BEDROCK_PREMIER_MODEL`

#### `providers.litellm_bedrock.models.embedding_model`

Embedding model for Bedrock

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_BEDROCK__MODELS__EMBEDDING_MODEL`
* **Environment default:** `BEDROCK_EMBEDDING_MODEL`

### providers.litellm\_bedrock.model\_selection\_mode

#### `providers.litellm_bedrock.model_selection_mode.default_chat`

Provenance of default\_chat

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__LITELLM_BEDROCK__MODEL_SELECTION_MODE__DEFAULT_CHAT`

#### `providers.litellm_bedrock.model_selection_mode.fast_model`

Provenance of fast\_model

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__LITELLM_BEDROCK__MODEL_SELECTION_MODE__FAST_MODEL`

#### `providers.litellm_bedrock.model_selection_mode.premier_model`

Provenance of premier\_model

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__LITELLM_BEDROCK__MODEL_SELECTION_MODE__PREMIER_MODEL`

### providers.litellm\_bedrock.model\_deferral

#### `providers.litellm_bedrock.model_deferral.default_chat`

Written by Genesis: why default\_chat waits for a new Genesis default (JSON: target, previous, last\_error, first\_deferred\_at, last\_probed\_at). Empty unless model\_selection\_mode.default\_chat is deferred\_default.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_BEDROCK__MODEL_DEFERRAL__DEFAULT_CHAT`

#### `providers.litellm_bedrock.model_deferral.fast_model`

Written by Genesis: why fast\_model waits for a new Genesis default (JSON: target, previous, last\_error, first\_deferred\_at, last\_probed\_at). Empty unless model\_selection\_mode.fast\_model is deferred\_default.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_BEDROCK__MODEL_DEFERRAL__FAST_MODEL`

#### `providers.litellm_bedrock.model_deferral.premier_model`

Written by Genesis: why premier\_model waits for a new Genesis default (JSON: target, previous, last\_error, first\_deferred\_at, last\_probed\_at). Empty unless model\_selection\_mode.premier\_model is deferred\_default.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_BEDROCK__MODEL_DEFERRAL__PREMIER_MODEL`

### providers.litellm\_gemini

#### `providers.litellm_gemini.admission`

auto: sufficient parameters permit use; any other value refuses the provider

* **Type:** `str`
* **Default:** `"auto"`
* **Options:** `auto`, `deny`
* **Override:** `GENESIS__PROVIDERS__LITELLM_GEMINI__ADMISSION`
* **Environment default:** `GEMINI_ADMISSION`

### providers.litellm\_gemini.connection

#### `providers.litellm_gemini.connection.api_key`

Google Gemini API key

* **Type:** `str`
* **Override:** `GENESIS__PROVIDERS__LITELLM_GEMINI__CONNECTION__API_KEY`
* **Startup environment variable:** `GEMINI_API_KEY`
* **Secret**

### providers.litellm\_gemini.settings

#### `providers.litellm_gemini.settings.default_model_tier`

Default model tier for Gemini

* **Type:** `str`
* **Default:** `"frontier"`
* **Options:** `frontier`, `main`, `fast`
* **Override:** `GENESIS__PROVIDERS__LITELLM_GEMINI__SETTINGS__DEFAULT_MODEL_TIER`

### providers.litellm\_gemini.models

#### `providers.litellm_gemini.models.default_chat`

Default Gemini chat model

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_GEMINI__MODELS__DEFAULT_CHAT`
* **Environment default:** `GEMINI_MODEL_NAME`, `GEMINI_MODEL`

#### `providers.litellm_gemini.models.fast_model`

Google Gemini fast model name

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_GEMINI__MODELS__FAST_MODEL`
* **Environment default:** `GEMINI_FAST_MODEL_NAME`

#### `providers.litellm_gemini.models.embedding_model`

Embedding model for Gemini

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_GEMINI__MODELS__EMBEDDING_MODEL`
* **Environment default:** `GEMINI_EMBEDDING_MODEL`

### providers.litellm\_gemini.model\_selection\_mode

#### `providers.litellm_gemini.model_selection_mode.default_chat`

Provenance of default\_chat

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__LITELLM_GEMINI__MODEL_SELECTION_MODE__DEFAULT_CHAT`

#### `providers.litellm_gemini.model_selection_mode.fast_model`

Provenance of fast\_model

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__LITELLM_GEMINI__MODEL_SELECTION_MODE__FAST_MODEL`

### providers.litellm\_gemini.model\_deferral

#### `providers.litellm_gemini.model_deferral.default_chat`

Written by Genesis: why default\_chat waits for a new Genesis default (JSON: target, previous, last\_error, first\_deferred\_at, last\_probed\_at). Empty unless model\_selection\_mode.default\_chat is deferred\_default.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_GEMINI__MODEL_DEFERRAL__DEFAULT_CHAT`

#### `providers.litellm_gemini.model_deferral.fast_model`

Written by Genesis: why fast\_model waits for a new Genesis default (JSON: target, previous, last\_error, first\_deferred\_at, last\_probed\_at). Empty unless model\_selection\_mode.fast\_model is deferred\_default.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_GEMINI__MODEL_DEFERRAL__FAST_MODEL`

### providers.litellm\_proxy

#### `providers.litellm_proxy.admission`

auto: sufficient parameters permit use; any other value refuses the provider

* **Type:** `str`
* **Default:** `"auto"`
* **Options:** `auto`, `deny`
* **Override:** `GENESIS__PROVIDERS__LITELLM_PROXY__ADMISSION`
* **Environment default:** `LITELLM_PROXY_ADMISSION`

### providers.litellm\_proxy.connection

#### `providers.litellm_proxy.connection.auth_mode`

LiteLLM Proxy authentication mode

* **Type:** `str`
* **Default:** `"api_key"`
* **Options:** `api_key`, `static_headers`, `oauth`, `none`
* **Override:** `GENESIS__PROVIDERS__LITELLM_PROXY__CONNECTION__AUTH_MODE`
* **Environment default:** `LITELLM_PROXY_AUTH_MECHANISM`

#### `providers.litellm_proxy.connection.transport`

Wire transport for proxy chat: 'auto' (default) sends Anthropic-family models to the native /v1/messages route and other models to OpenAI-compatible /chat/completions; 'openai' or 'anthropic' pins one route. Pin 'openai' if the proxy has no /v1/messages route, or authenticates only on Authorization while auth\_mode is api\_key or static\_headers.

* **Type:** `str`
* **Default:** `"auto"`
* **Options:** `auto`, `openai`, `anthropic`
* **Override:** `GENESIS__PROVIDERS__LITELLM_PROXY__CONNECTION__TRANSPORT`
* **Environment default:** `LITELLM_PROXY_TRANSPORT`

#### `providers.litellm_proxy.connection.base_url`

LiteLLM Proxy base URL

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_PROXY__CONNECTION__BASE_URL`
* **Environment default:** `LITELLM_PROXY_API_BASE`

#### `providers.litellm_proxy.connection.anthropic_base_url`

Optional base URL for the native Anthropic Messages route (for example https\://\<host>/ai-gateway/anthropic/v1), for gateways that serve it apart from the OpenAI-compatible route. When set, chat on the Anthropic transport is sent here; utility calls, embeddings and model discovery keep base\_url. Empty (the default) derives the Anthropic route from base\_url.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_PROXY__CONNECTION__ANTHROPIC_BASE_URL`
* **Environment default:** `LITELLM_PROXY_ANTHROPIC_API_BASE`

### providers.litellm\_proxy.connection.api\_key

#### `providers.litellm_proxy.connection.api_key.key`

LiteLLM Proxy API key

* **Type:** `str`
* **Override:** `GENESIS__PROVIDERS__LITELLM_PROXY__CONNECTION__API_KEY__KEY`
* **Startup environment variable:** `LITELLM_PROXY_API_KEY`
* **Secret**

### providers.litellm\_proxy.connection.static\_headers

#### `providers.litellm_proxy.connection.static_headers.headers_json`

JSON object of static headers used when auth\_mode=static\_headers

* **Type:** `str`
* **Override:** `GENESIS__PROVIDERS__LITELLM_PROXY__CONNECTION__STATIC_HEADERS__HEADERS_JSON`
* **Startup environment variable:** `LITELLM_PROXY_STATIC_HEADERS_JSON`
* **Secret**

### providers.litellm\_proxy.connection.oauth

#### `providers.litellm_proxy.connection.oauth.authorization_url`

OAuth authorization endpoint for per-user LiteLLM Proxy browser flows

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_PROXY__CONNECTION__OAUTH__AUTHORIZATION_URL`
* **Environment default:** `LITELLM_PROXY_OAUTH_AUTHORIZATION_URL`

#### `providers.litellm_proxy.connection.oauth.token_url`

OAuth token endpoint used when auth\_mode=oauth

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_PROXY__CONNECTION__OAUTH__TOKEN_URL`
* **Environment default:** `LITELLM_PROXY_OAUTH_TOKEN_URL`

#### `providers.litellm_proxy.connection.oauth.client_id`

OAuth client ID used when auth\_mode=oauth (supports aws\_*, secret\_*, env\_\* references)

* **Type:** `str`
* **Override:** `GENESIS__PROVIDERS__LITELLM_PROXY__CONNECTION__OAUTH__CLIENT_ID`
* **Startup environment variable:** `LITELLM_PROXY_OAUTH_CLIENT_ID`
* **Secret**

#### `providers.litellm_proxy.connection.oauth.client_secret`

OAuth client secret reference/value used when auth\_mode=oauth

* **Type:** `str`
* **Override:** `GENESIS__PROVIDERS__LITELLM_PROXY__CONNECTION__OAUTH__CLIENT_SECRET`
* **Startup environment variable:** `LITELLM_PROXY_OAUTH_CLIENT_SECRET`
* **Secret**

#### `providers.litellm_proxy.connection.oauth.token_endpoint_auth_method`

How LiteLLM Proxy OAuth client credentials are sent to the token endpoint

* **Type:** `str`
* **Default:** `"client_secret_post"`
* **Options:** `client_secret_post`, `client_secret_basic`, `none`
* **Override:** `GENESIS__PROVIDERS__LITELLM_PROXY__CONNECTION__OAUTH__TOKEN_ENDPOINT_AUTH_METHOD`
* **Environment default:** `LITELLM_PROXY_OAUTH_TOKEN_ENDPOINT_AUTH_METHOD`

#### `providers.litellm_proxy.connection.oauth.scopes`

Space-delimited OAuth scopes used for LiteLLM Proxy OAuth

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_PROXY__CONNECTION__OAUTH__SCOPES`
* **Environment default:** `LITELLM_PROXY_OAUTH_SCOPES`

#### `providers.litellm_proxy.connection.oauth.request_refresh_token`

Add the offline\_access scope to each person's LiteLLM Proxy sign-in, so the grant carries a refresh token and renews itself. Turn off for an identity provider that rejects offline\_access as an unknown scope (Amazon Cognito, Google, PingFederate).

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__PROVIDERS__LITELLM_PROXY__CONNECTION__OAUTH__REQUEST_REFRESH_TOKEN`
* **Environment default:** `LITELLM_PROXY_OAUTH_REQUEST_REFRESH_TOKEN`

#### `providers.litellm_proxy.connection.oauth.custom_header_descriptors`

Supplemental custom header descriptors for LiteLLM Proxy OAuth token exchange and downstream calls

* **Type:** `list`
* **Default:** `[]`
* **Override:** `GENESIS__PROVIDERS__LITELLM_PROXY__CONNECTION__OAUTH__CUSTOM_HEADER_DESCRIPTORS`
* **Environment default:** `LITELLM_PROXY_OAUTH_CUSTOM_HEADER_DESCRIPTORS_JSON`

#### `providers.litellm_proxy.connection.oauth.service_account_header_values`

Service-account header values as a dict (preferred over \_json for config files)

* **Type:** `dict`
* **Default:** `{}`
* **Override:** `GENESIS__PROVIDERS__LITELLM_PROXY__CONNECTION__OAUTH__SERVICE_ACCOUNT_HEADER_VALUES`

#### `providers.litellm_proxy.connection.oauth.service_account_header_values_json`

JSON-encoded service-account header values (secret ref or literal JSON string). Ignored when service\_account\_header\_values dict is set.

* **Type:** `str`
* **Override:** `GENESIS__PROVIDERS__LITELLM_PROXY__CONNECTION__OAUTH__SERVICE_ACCOUNT_HEADER_VALUES_JSON`
* **Startup environment variable:** `LITELLM_PROXY_OAUTH_SERVICE_ACCOUNT_HEADER_VALUES_JSON`
* **Secret**

### providers.litellm\_proxy.settings

#### `providers.litellm_proxy.settings.oauth_credential_policy`

Admin-only policy controlling whether LiteLLM Proxy uses per-user OAuth, service-account OAuth, or per-user OAuth with service fallback.

* **Type:** `str`
* **Default:** `"per_user_oauth"`
* **Options:** `per_user_oauth`, `service_account`, `per_user_oauth_with_service_fallback`
* **Override:** `GENESIS__PROVIDERS__LITELLM_PROXY__SETTINGS__OAUTH_CREDENTIAL_POLICY`
* **Environment default:** `LITELLM_PROXY_OAUTH_CREDENTIAL_POLICY`

#### `providers.litellm_proxy.settings.allow_user_oauth_fallback_for_non_interactive`

Admin-only emergency fallback allowing non-interactive LiteLLM Proxy runs to use the originating user's OAuth grant when service-account execution is unavailable.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__PROVIDERS__LITELLM_PROXY__SETTINGS__ALLOW_USER_OAUTH_FALLBACK_FOR_NON_INTERACTIVE`
* **Environment default:** `LITELLM_PROXY_ALLOW_USER_OAUTH_FALLBACK_FOR_NON_INTERACTIVE`

#### `providers.litellm_proxy.settings.default_model_tier`

Default model tier for LiteLLM Proxy

* **Type:** `str`
* **Default:** `"frontier"`
* **Options:** `frontier`, `main`, `fast`
* **Override:** `GENESIS__PROVIDERS__LITELLM_PROXY__SETTINGS__DEFAULT_MODEL_TIER`

#### `providers.litellm_proxy.settings.underlying_models`

Maps a proxy chat model id to the known model it serves (for example \{"main.genesis.opus-5-5-genesis": "claude-opus-5-5"}), so Genesis uses that model's context window and output limit. For limits it is consulted only for a model the proxy's own model catalog does not describe, such as a gateway that answers no model-info request. An alias mapped to a Claude model also takes the Anthropic Messages route when the transport is Automatic.

* **Type:** `dict`
* **Default:** `{}`
* **Override:** `GENESIS__PROVIDERS__LITELLM_PROXY__SETTINGS__UNDERLYING_MODELS`

#### `providers.litellm_proxy.settings.issued_by_genesis`

True while this proxy connection holds the Genesis AI key Genesis Desktop issued (set by Genesis Desktop, never by hand). The provider is then shown as Genesis AI, and its model assignments are fixed to the Genesis AI models and refused through the API. Cleared whenever a proxy connection is saved, except by Genesis Desktop saving the key it issued.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__PROVIDERS__LITELLM_PROXY__SETTINGS__ISSUED_BY_GENESIS`

### providers.litellm\_proxy.models

#### `providers.litellm_proxy.models.default_chat`

Default LiteLLM Proxy chat model

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_PROXY__MODELS__DEFAULT_CHAT`
* **Environment default:** `LITELLM_PROXY_MODEL_NAME`

#### `providers.litellm_proxy.models.fast_model`

LiteLLM Proxy fast model

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_PROXY__MODELS__FAST_MODEL`
* **Environment default:** `LITELLM_PROXY_FAST_MODEL_NAME`

#### `providers.litellm_proxy.models.premier_model`

LiteLLM Proxy premiere model

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_PROXY__MODELS__PREMIER_MODEL`
* **Environment default:** `LITELLM_PROXY_PREMIER_MODEL`

#### `providers.litellm_proxy.models.fallback_model`

Chat model a turn is re-sent to once when its own model is unavailable, keeps failing with a server error or stays rate limited after its retries. Never used for authentication, permission or invalid-request errors, after any output has been shown, or for a turn pinned to an exact model. Cost: the fallback runs only after the failed model has spent its own retries, so while the main model is down every turn first waits through its transient retries and, for a rate limit, up to llm.rate\_limit\_recovery\_seconds. Empty (the default) turns the fallback off.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_PROXY__MODELS__FALLBACK_MODEL`
* **Environment default:** `LITELLM_PROXY_FALLBACK_MODEL`

#### `providers.litellm_proxy.models.embedding_model`

Embedding model for LiteLLM Proxy

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__PROVIDERS__LITELLM_PROXY__MODELS__EMBEDDING_MODEL`
* **Environment default:** `LITELLM_PROXY_EMBEDDING_MODEL`

### providers.litellm\_proxy.model\_selection\_mode

#### `providers.litellm_proxy.model_selection_mode.default_chat`

Provenance of default\_chat

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__LITELLM_PROXY__MODEL_SELECTION_MODE__DEFAULT_CHAT`

#### `providers.litellm_proxy.model_selection_mode.fast_model`

Provenance of fast\_model

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__LITELLM_PROXY__MODEL_SELECTION_MODE__FAST_MODEL`

#### `providers.litellm_proxy.model_selection_mode.premier_model`

Provenance of premier\_model

* **Type:** `str`
* **Default:** `""`
* **Options:** `default`, `override`, `deferred_default`
* **Override:** `GENESIS__PROVIDERS__LITELLM_PROXY__MODEL_SELECTION_MODE__PREMIER_MODEL`

### providers.voyage

#### `providers.voyage.admission`

auto: sufficient parameters permit use; any other value refuses the provider

* **Type:** `str`
* **Default:** `"auto"`
* **Options:** `auto`, `deny`
* **Override:** `GENESIS__PROVIDERS__VOYAGE__ADMISSION`
* **Environment default:** `VOYAGE_ADMISSION`

### providers.voyage.connection

#### `providers.voyage.connection.api_key`

Voyage AI API key for embeddings

* **Type:** `str`
* **Override:** `GENESIS__PROVIDERS__VOYAGE__CONNECTION__API_KEY`
* **Startup environment variable:** `VOYAGE_API_KEY`
* **Secret**

## Embedding

#### `embedding.active_provider`

Active embedding provider (references a providers.\* key)

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__EMBEDDING__ACTIVE_PROVIDER`
* **Environment default:** `EMBEDDING_PROVIDER`

#### `embedding.active_model`

Active embedding model (global). Per-provider defaults live in providers.\<p>.models.embedding\_model.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__EMBEDDING__ACTIVE_MODEL`
* **Environment default:** `EMBEDDING_MODEL`

#### `embedding.active_dimensions`

Vector size the embeddings test observed for embedding.active\_dimensions\_model, a model no catalog describes (a Unity AI Gateway model service, an Azure deployment). Written by the embeddings save; 0 when nothing was observed. Used only while that model is embedding.active\_model and the catalog gives no size for it.

* **Type:** `int`
* **Default:** `0`
* **Minimum:** `0`
* **Override:** `GENESIS__EMBEDDING__ACTIVE_DIMENSIONS`

#### `embedding.active_dimensions_model`

Embedding model embedding.active\_dimensions was observed for. The size is ignored for any other model, so a later change of embedding.active\_model, however it is written, never inherits it.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__EMBEDDING__ACTIVE_DIMENSIONS_MODEL`

## Threads & Messages

#### `threads.max_messages`

Maximum total messages allowed in a thread (0 = unlimited)

* **Type:** `int`
* **Default:** `0`
* **Override:** `GENESIS__THREADS__MAX_MESSAGES`
* **Environment default:** `THREAD_MAX_MESSAGES`

#### `threads.max_user_messages`

Maximum user messages allowed in a thread (0 = unlimited)

* **Type:** `int`
* **Default:** `0`
* **Override:** `GENESIS__THREADS__MAX_USER_MESSAGES`
* **Environment default:** `THREAD_MAX_USER_MESSAGES`

#### `threads.max_message_size_bytes`

Maximum size of user message text in bytes (16KB default). File uploads handled separately.

* **Type:** `int`
* **Default:** `16384`
* **Override:** `GENESIS__THREADS__MAX_MESSAGE_SIZE_BYTES`
* **Environment default:** `MAX_MESSAGE_SIZE_BYTES`

#### `threads.export_include_query_results`

Bundle cached query results into thread ZIP exports so query-result embeds still resolve after importing on another server. Callers can override per-export via the include\_query\_results query param.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__THREADS__EXPORT_INCLUDE_QUERY_RESULTS`

#### `threads.export_max_query_results_bytes`

Size cap (bytes) for the bundled query\_results/results.json in a thread ZIP export. When the serialized results exceed this, they are omitted rather than bloating the archive (25MB default).

* **Type:** `int`
* **Default:** `25000000`
* **Override:** `GENESIS__THREADS__EXPORT_MAX_QUERY_RESULTS_BYTES`
* **Environment default:** `THREAD_EXPORT_MAX_QUERY_RESULTS_BYTES`

#### `threads.default_visibility`

Default visibility for new threads

* **Type:** `str`
* **Default:** `"public"`
* **Options:** `public`, `private`
* **Override:** `GENESIS__THREADS__DEFAULT_VISIBILITY`
* **Environment default:** `DEFAULT_THREAD_VISIBILITY`

#### `threads.user_message_limit`

Maximum messages per user (0 = unlimited)

* **Type:** `int`
* **Default:** `0`
* **Override:** `GENESIS__THREADS__USER_MESSAGE_LIMIT`
* **Environment default:** `USER_MESSAGE_LIMIT`

#### `threads.memory_threshold_mb`

Memory threshold for LRU thread eviction in megabytes

* **Type:** `int`
* **Default:** `1000`
* **Override:** `GENESIS__THREADS__MEMORY_THRESHOLD_MB`
* **Environment default:** `THREAD_MEMORY_THRESHOLD_MB`

#### `threads.disable_auto_title`

Disable automatic thread title generation

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__THREADS__DISABLE_AUTO_TITLE`
* **Environment default:** `DISABLE_THREAD_TITLE_GENERATION`

### threads.storage

#### `threads.storage.snapshot_cache_mb`

Postgres thread storage only (GENESIS\_THREAD\_STORAGE\_BACKEND=postgres): memory, in MB per process, for recently read thread snapshot documents, so each short-lived write-path open does not pull the whole snapshot row from the database again. Entries never go stale; the budget only bounds memory. 0 turns the cache off. Read at every insert, so a change applies without a restart.

* **Type:** `int`
* **Default:** `64`
* **Minimum:** `0`
* **Override:** `GENESIS__THREADS__STORAGE__SNAPSHOT_CACHE_MB`

### threads.search

#### `threads.search.enabled`

Enable thread search indexing (ChromaDB). Disable to skip indexing entirely.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__THREADS__SEARCH__ENABLED`
* **Environment default:** `THREAD_SEARCH_ENABLED`

#### `threads.search.index_workers`

Number of background threads for search indexing

* **Type:** `int`
* **Default:** `1`
* **Override:** `GENESIS__THREADS__SEARCH__INDEX_WORKERS`
* **Environment default:** `THREAD_SEARCH_INDEX_WORKERS`

#### `threads.search.build_rss_growth_ceiling_mb`

How far (MB) the thread-service worker's resident memory may grow above where it stood when the background index build began before the build releases memory and indexes one thread at a time until it is back under. Bounds the build's peak on large estates, where the parallel build otherwise pushed the worker into the container's OOM killer (GEN-3971). 0 turns the bound off.

* **Type:** `int`
* **Default:** `1536`
* **Override:** `GENESIS__THREADS__SEARCH__BUILD_RSS_GROWTH_CEILING_MB`
* **Environment default:** `THREAD_SEARCH_BUILD_RSS_GROWTH_CEILING_MB`

#### `threads.search.min_content_length`

Minimum message length (chars) to index. Shorter messages are skipped.

* **Type:** `int`
* **Default:** `10`
* **Override:** `GENESIS__THREADS__SEARCH__MIN_CONTENT_LENGTH`
* **Environment default:** `THREAD_SEARCH_MIN_CONTENT_LENGTH`

#### `threads.search.startup_seed_threads`

On startup, index the N most-recent threads first (sorted newest-first by last\_activity) before fanning the remaining threads out to the parallel builder. Makes search\_messages return hits for the hot set almost immediately instead of waiting for the full build to complete. Runs on the thread\_search\_index executor, so it does not block FastAPI startup. Set to 0 to disable seeding.

* **Type:** `int`
* **Default:** `200`
* **Override:** `GENESIS__THREADS__SEARCH__STARTUP_SEED_THREADS`
* **Environment default:** `THREAD_SEARCH_STARTUP_SEED_THREADS`

### threads.summary\_warming

#### `threads.summary_warming.enabled`

Background summary cache warming ("always ready"): when a thread's measured prompt usage crosses usage\_floor\_pct of its effective context ceiling, a maintenance-priority background job pre-computes V6 window summaries into a per-thread sidecar file (\<thread>.summaries.json). A later over-limit recovery compression then reuses the cached summaries and completes without LLM work. Never rewrites the thread; recovery still triggers only at the actual limit.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__THREADS__SUMMARY_WARMING__ENABLED`

#### `threads.summary_warming.usage_floor_pct`

Start warming once provider-reported prompt tokens plus reserved output budget exceed this percentage of the thread's effective context ceiling. Short threads that never compress never pay for warming.

* **Type:** `int`
* **Default:** `45`
* **Override:** `GENESIS__THREADS__SUMMARY_WARMING__USAGE_FLOOR_PCT`

#### `threads.summary_warming.cooldown_seconds`

Minimum seconds between warm-job enqueues for one thread, so a fast-growing thread does not schedule a pass after every turn. Re-warming an already-cached window is a cache hit, not an LLM call, so occasional extra passes are cheap.

* **Type:** `int`
* **Default:** `120`
* **Override:** `GENESIS__THREADS__SUMMARY_WARMING__COOLDOWN_SECONDS`

#### `threads.summary_warming.sprint_usage_pct`

Frontier sprint mode: once measured usage exceeds this percentage of the effective ceiling, the cooldown is bypassed so a warm pass is enqueued after every turn. Near the limit, the windows recovery will need are the ones being created right now — waiting out the cooldown is what leaves them cold. Set to 0 to disable (always sprint) or above 100 to never sprint.

* **Type:** `int`
* **Default:** `85`
* **Override:** `GENESIS__THREADS__SUMMARY_WARMING__SPRINT_USAGE_PCT`

#### `threads.summary_warming.max_windows_per_pass`

Cap on how many history windows a single warm pass may summarize (oldest first). 0 = no cap (warm every eligible window).

* **Type:** `int`
* **Default:** `0`
* **Override:** `GENESIS__THREADS__SUMMARY_WARMING__MAX_WINDOWS_PER_PASS`

#### `threads.summary_warming.sidecar_max_entries`

Maximum summary entries kept in a thread's .summaries.json sidecar (pruned LRU by update time). Entries are \~2KB each.

* **Type:** `int`
* **Default:** `512`
* **Override:** `GENESIS__THREADS__SUMMARY_WARMING__SIDECAR_MAX_ENTRIES`

## Context Management Improvements

#### `context_management_improvements.archive_tool_calls_on_compression`

Archive tool call arguments and tool results as the first step of every compaction pass, before any LLM summarization runs. Tool traffic carries most of a long thread's bytes, and everything archived can be served again: the full payload is written to the compression artifact store and read back with manage\_thread\_memory(action= 'GET\_COMPRESSED\_TOOL\_RESULT') for a result or 'GET\_COMPRESSED\_PARAM\_ARCHIVE' for arguments, while a result produced by a file read also names its path so the model can simply re-read the file. The step makes no LLM call, so a pass that reaches its byte target here finishes with zero summary calls. Turn off to restore the previous behaviour, where every old message including tool traffic went straight to the summarizer.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__CONTEXT_MANAGEMENT_IMPROVEMENTS__ARCHIVE_TOOL_CALLS_ON_COMPRESSION`

#### `context_management_improvements.max_never_compress_skills_per_agent`

How many of an agent's default skills may be marked "never compress". A never-compress skill keeps its full injected text through every summary and through automatic overflow recovery, so it costs its tokens on every turn. Adding flags beyond this many is refused; lowering it never removes flags already set. 0 stops new flags being added.

* **Type:** `int`
* **Default:** `3`
* **Minimum:** `0`
* **Maximum:** `20`
* **Override:** `GENESIS__CONTEXT_MANAGEMENT_IMPROVEMENTS__MAX_NEVER_COMPRESS_SKILLS_PER_AGENT`

## Goal Mode

#### `goal_mode.max_nudges`

How many times a blueprint phase running in goal mode is nudged on without the agent reporting any progress against the goal before the nudging stops and the goal waits for a person. Goal mode is the third blueprint run mode: the phase's own exit criteria are the finish line the agent reports against, and a nudge is the only thing the mode spends by itself, so this is the only budget it has. It never ends a goal -- running out of nudges leaves the work exactly where someone can pick it up. A change applies to goals created afterwards; a goal already running keeps the budget it started with.

* **Type:** `int`
* **Default:** `3`
* **Minimum:** `1`
* **Override:** `GENESIS__GOAL_MODE__MAX_NUDGES`

#### `goal_mode.max_total_nudges`

How many nudges one goal-mode phase may be sent in total, however much progress its agent reports. A backstop, not a ceiling on how much work a phase may do: max\_nudges is reset by progress, and "progress" includes the agent reporting something new in its own words, which an agent stuck in a loop can do every turn by varying its wording. Nothing resets this one, so there is always a number of nudges after which a person is involved. Like max\_nudges it never ends a goal -- it stops the nudging and leaves the work where someone can pick it up. Raise it for long autonomous missions.

* **Type:** `int`
* **Default:** `50`
* **Minimum:** `1`
* **Override:** `GENESIS__GOAL_MODE__MAX_TOTAL_NUDGES`

#### `goal_mode.checkin_quiet_minutes`

How many minutes a goal-mode Blueprint run's thread may go without any sign of its agent -- no turn running and none ended -- before the agent is woken with a check-in asking it to look at what is going on: confirm a run or agent it is waiting on is still going, carry on from a result that came back, or ask the person if it is stuck. Applies while the run is waiting on an external run or another agent too, because those waits are only as good as the wake that ends them. At most one check-in per this interval per run. Read on every sweep, so a change applies at once.

* **Type:** `int`
* **Default:** `15`
* **Minimum:** `1`
* **Maximum:** `1440`
* **Override:** `GENESIS__GOAL_MODE__CHECKIN_QUIET_MINUTES`

#### `goal_mode.max_quiet_checkins`

How many check-ins in a row a quiet goal-mode run may be sent without its goal moving before the check-ins stop and the run is shown waiting on a person: its phase is marked awaiting input and the run records that it stalled. Any real progress on the goal, or a message from a person, starts the count again. Not while any run the goal's thread commissioned (a seat, prove, grade or characterize run, say) is still running with a fresh heartbeat: the check-ins carry on, one per interval for as long as that lasts, and the run is shown waiting on a person once that run ends or its heartbeat goes stale.

* **Type:** `int`
* **Default:** `3`
* **Minimum:** `1`
* **Maximum:** `50`
* **Override:** `GENESIS__GOAL_MODE__MAX_QUIET_CHECKINS`

#### `goal_mode.max_llm_failures`

How many turns in a row a goal-mode thread may lose to a model-service failure (a rate limit, a timeout, an outage, an empty completion) before goal mode stops retrying and leaves the goal for a person, with the reason shown as the model service being unavailable. Below it, each failed turn is retried after a wait that starts at one minute and doubles, up to ten minutes. The first turn that gets a reply starts the count again. Read at the end of every turn, so a change applies at once.

* **Type:** `int`
* **Default:** `3`
* **Minimum:** `1`
* **Maximum:** `20`
* **Override:** `GENESIS__GOAL_MODE__MAX_LLM_FAILURES`

## Tools

### tools.cancellation

#### `tools.cancellation.abort_deadline_seconds`

How long one driver abort may hold the thread that is stopping a tool call, in seconds. Stopping a tool tells each database server to stop the statement it is still running; that is a network round trip issued from the polling thread, and neither pyodbc's SQLCancel nor Snowflake's abort-request accepts a timeout of its own, so a server that stops answering would otherwise hold a shared-executor thread indefinitely. Measured round trips against real SQL Server, Snowflake and Databricks SQL were 0.14-2.0s, so the default leaves roughly five times the slowest observed abort before it trips. Set to 0 to wait indefinitely (the pre-GEN-2843 behaviour).

* **Type:** `float`
* **Default:** `10.0`
* **Minimum:** `0.0`
* **Override:** `GENESIS__TOOLS__CANCELLATION__ABORT_DEADLINE_SECONDS`

#### `tools.cancellation.total_deadline_seconds`

Ceiling on the whole stop path, in seconds, across every in-flight statement a tool call holds. The user's "stopped" response waits on these aborts, so this bounds how long a stop can take when several statements are registered and servers are slow. Statements still unaborted when it expires are logged and abandoned. Set to 0 for no overall ceiling.

* **Type:** `float`
* **Default:** `30.0`
* **Minimum:** `0.0`
* **Override:** `GENESIS__TOOLS__CANCELLATION__TOTAL_DEADLINE_SECONDS`

### tools.execution

#### `tools.execution.max_tool_worker_threads`

Ceiling on tool-worker threads alive at once across the whole server. Every agent tool call runs on its own worker thread so the call can be stopped while it runs, and a stopped call's worker is abandoned and keeps its thread until the tool returns; without a ceiling those threads grow past the server's thread budget. A tool call arriving while this many workers are alive is refused, not queued: nothing is executed and the agent is told to retry. The default matches the shared 20-thread executor the calls are dispatched from, so ordinary load never reaches it; it is reached when abandoned workers pile up. Read on every tool call.

* **Type:** `int`
* **Default:** `20`
* **Minimum:** `1`
* **Override:** `GENESIS__TOOLS__EXECUTION__MAX_TOOL_WORKER_THREADS`

#### `tools.execution.cancel_grace_seconds`

How long a stopped tool call may take to end, in seconds, before its worker thread is abandoned. When a person stops an agent, the tool call it is running has its abort hooks fired at once (a warehouse statement cancelled, a subprocess group killed); this is the time it then gets to notice and return, so the stop can report honestly that the work was cancelled. Past it the call is abandoned and reported as such. Long enough for a driver cancel to land, short enough for the stop to feel immediate. Read on every stop.

* **Type:** `float`
* **Default:** `5.0`
* **Minimum:** `0.0`
* **Override:** `GENESIS__TOOLS__EXECUTION__CANCEL_GRACE_SECONDS`

#### `tools.execution.cancel_grace_seconds_by_tool`

Per-tool overrides of cancel\_grace\_seconds, keyed by the tool's function name, for example \{"run\_dbt\_command": 15}. A value that is not a non-negative number is ignored with a warning and the default applies. Read on every stop.

* **Type:** `dict`
* **Default:** `{}`
* **Override:** `GENESIS__TOOLS__EXECUTION__CANCEL_GRACE_SECONDS_BY_TOOL`

### tools.databricks

#### `tools.databricks.unity_catalog_pages_enabled`

Whether the databricks\_action verbs that author Unity Catalog Pages (create\_uc\_page, publish\_uc\_page, list\_uc\_pages, delete\_uc\_page, bulk\_create\_uc\_pages) may run. False, the default, is a stated refusal: each of the five returns success false naming this field, and nothing is sent to the workspace. It is never a silent no-op, because a caller cannot tell one from a glossary that published nothing. Off by default because Unity Catalog Pages has NO public API. These verbs reach it through the API the Databricks console itself calls, which is undocumented, unsupported and fenced by a request signature and an allowlist of operation names, so it can stop working on any console release with no notice, no versioning and no deprecation window. They are one-shot bootstrap tooling for seeding or migrating a glossary on request -- a person or an agent turns this on, runs the import, and turns it off. Do NOT enable it for anything that runs on a schedule: the failure modes are responses this API has not produced before, which an attended run surfaces to a human and an unattended one turns into a silent wrong answer. Read at call time, so switching it off stops the next call without a restart.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__TOOLS__DATABRICKS__UNITY_CATALOG_PAGES_ENABLED`

### tools.web\_access

#### `tools.web_access.default_search_provider`

Provider used by search\_web when provider='auto'. Defaults to 'serper' so that merely adding a Tavily key never silently reroutes auto search traffic (and its per-call cost). Set to 'tavily' to prefer Tavily as the auto default. Explicit provider= arguments always override this; if the chosen default has no key configured, search\_web falls back to whichever provider does.

* **Type:** `str`
* **Default:** `"serper"`
* **Options:** `serper`, `tavily`
* **Override:** `GENESIS__TOOLS__WEB_ACCESS__DEFAULT_SEARCH_PROVIDER`
* **Environment default:** `WEB_ACCESS_DEFAULT_SEARCH_PROVIDER`

### tools.gitlab

#### `tools.gitlab.request_timeout_seconds`

HTTP timeout (seconds) for every GitLab REST API call made by the GitLab connector (repo listing, merge requests, file operations). Raise this if a large or slow GitLab instance times out while listing projects for the Context Graph repo picker; the previous hardcoded 10s aborted listings whenever gitlab.com took longer than 10s to start answering any single paginated request.

* **Type:** `int`
* **Default:** `30`
* **Override:** `GENESIS__TOOLS__GITLAB__REQUEST_TIMEOUT_SECONDS`

### tools.ocr

#### `tools.ocr.databricks_volume_path`

Unity Catalog volume the OCR tool's Databricks method (ai\_parse\_document) uploads files to, as the volume root /Volumes/\<catalog>/\<schema>/\<volume> (a subpath is refused). Each call uploads to its own genesis\_ocr/ subpath and tries to delete the file afterwards (a failed delete is logged). The Databricks connection OCR runs on must hold READ VOLUME and WRITE VOLUME on it. Required in a Databricks App, where it is the only upload location. Elsewhere, empty keeps the older guess, /Volumes/workspace/default/\<bot>\_workspace with a DBFS fallback, and a path passed to the tool call still wins.

* **Type:** `string`
* **Default:** `""`
* **Override:** `GENESIS__TOOLS__OCR__DATABRICKS_VOLUME_PATH`

### tools.output\_governor

#### `tools.output_governor.python_budget_bytes`

Maximum size (bytes) of an `execute_python_code`-style tool result that can be inlined into conversation history. Outputs larger than this are capped to a short preview and the full content is spilled to a `truncated_tool_outputs/` artifact. Lowered from 96 KB to 32 KB to spill obviously-pathological outputs (which trigger an Anthropic Claude 4.x mid-stream hang on follow-up `tool_use` calls) while leaving legitimate \~21 KB analytics turns inline. Lower further (e.g. 10240 or 5000) if the stall is observed on smaller payloads. Changes take effect on the next tool call — no restart required.

* **Type:** `int`
* **Default:** `32768`
* **Override:** `GENESIS__TOOLS__OUTPUT_GOVERNOR__PYTHON_BUDGET_BYTES`
* **Environment default:** `GENESIS_TOOL_OUTPUT_PYTHON_BUDGET`

#### `tools.output_governor.inline_budget_bytes`

Default inline budget (bytes) for any tool output not in a more specific bucket. Same rationale and default as `python_budget_bytes`.

* **Type:** `int`
* **Default:** `32768`
* **Override:** `GENESIS__TOOLS__OUTPUT_GOVERNOR__INLINE_BUDGET_BYTES`
* **Environment default:** `GENESIS_TOOL_OUTPUT_INLINE_BUDGET`

#### `tools.output_governor.file_read_budget_bytes`

Inline budget (bytes) for file-read tools (`read_file`, `file(action="read")`, `git_action(action="read")`). Kept at 256 KB because legitimate source-file reads frequently exceed the 32 KB default budget and the user's explicit intent on a read action is to see the file. Lower this if the streaming stall pattern is observed on file-read flows.

* **Type:** `int`
* **Default:** `262144`
* **Override:** `GENESIS__TOOLS__OUTPUT_GOVERNOR__FILE_READ_BUDGET_BYTES`
* **Environment default:** `GENESIS_TOOL_OUTPUT_FILE_READ_BUDGET`

## Dbt

#### `dbt.max_concurrent_invocations`

Maximum number of dbt CLI invocations Genesis runs concurrently across different repositories. Calls within one repository serialize because they share project files and target artifacts. Each child has a private profiles dir and DBT\_PROFILES\_DIR, so parallel repositories cannot mix profile resolution. This bounds active child processes and warehouse/ database contention; waiters poll for tool cancellation. Generous by default and clamped to a minimum of 2 at runtime. Read once per process -- restart to change.

* **Type:** `int`
* **Default:** `8`
* **Override:** `GENESIS__DBT__MAX_CONCURRENT_INVOCATIONS`
* **Environment default:** `GENESIS_DBT_MAX_CONCURRENT_INVOCATIONS`

### dbt.safety

#### `dbt.safety.trusted_projects`

Allowlist of trusted dbt project names / git repo ids whose dbt\_action calls skip the dbt safety guards, including the LLM injection/access judge that otherwise adds latency. The static host-path and secret redaction in dbt\_action is a separate mechanism and always still runs. A call is trusted when its project\_name OR repo\_id matches an entry exactly (trimmed, case-sensitive). Accepts a YAML/JSON list or a comma-separated string. Empty (the default) keeps the guards enabled for every project — zero behaviour change out of the box.

* **Type:** `list`
* **Default:** `[]`
* **Override:** `GENESIS__DBT__SAFETY__TRUSTED_PROJECTS`

#### `dbt.safety.trusted_env_vars`

Explicit non-secret name/value pairs exposed through env\_var() only to projects matched by dbt.safety.trusted\_projects. Values come from this raw stored mapping, never from the Genesis server environment; env\_VAR and \$\{VAR} references are rejected. Names must be valid environment- variable identifiers. dbt, Python, dynamic-loader, and process startup control names are reserved. Empty (the default) exposes no values.

* **Type:** `dict`
* **Default:** `{}`
* **Override:** `GENESIS__DBT__SAFETY__TRUSTED_ENV_VARS`

## Sandbox

#### `sandbox.default_backend`

Default sandbox backend used when sandbox\_action(action="start") is called without an explicit backend. Set to "eks" on EKS deployments so agents use Kubernetes pods instead of local Docker. Valid values: local, eks, k8s, fargate, ecs\_ec2, railway.

* **Type:** `str`
* **Default:** `"local"`
* **Options:** `local`, `eks`, `k8s`, `fargate`, `ecs_ec2`, `railway`
* **Override:** `GENESIS__SANDBOX__DEFAULT_BACKEND`
* **Environment default:** `GENESIS_SANDBOX_DEFAULT_BACKEND`

## Sandbox Build

#### `sandbox_build`

Opaque per-object store of sandbox image-build records (config\_name sandbox\_build; one row per build\_\<hash>). Written and read by sandbox\_action via the ConfigAccessor; never descended by the config snapshot loader.

* **Type:** `dict`
* **Default:** `{}`
* **Override:** `GENESIS__SANDBOX_BUILD`

## Sandbox Image

#### `sandbox_image`

Opaque per-object store of built sandbox image records (one row per image key). Written and read by sandbox\_action via the ConfigAccessor; never descended by the config snapshot loader.

* **Type:** `dict`
* **Default:** `{}`
* **Override:** `GENESIS__SANDBOX_IMAGE`

## Sandbox Spec

#### `sandbox_spec`

Opaque per-object store of saved sandbox build specs (one row per spec name). Written and read by sandbox\_action via the ConfigAccessor; never descended by the config snapshot loader.

* **Type:** `dict`
* **Default:** `{}`
* **Override:** `GENESIS__SANDBOX_SPEC`

## Sandbox Target Env

#### `sandbox_target_env`

Opaque per-object store of named sandbox target-environment definitions (one row per name). Read by sandbox\_action via the ConfigAccessor; never descended by the config snapshot loader.

* **Type:** `dict`
* **Default:** `{}`
* **Override:** `GENESIS__SANDBOX_TARGET_ENV`

## Sandbox Security Profile

#### `sandbox_security_profile`

Opaque per-object store of named sandbox security profiles (one row per name). Read by sandbox\_action via the ConfigAccessor; never descended by the config snapshot loader.

* **Type:** `dict`
* **Default:** `{}`
* **Override:** `GENESIS__SANDBOX_SECURITY_PROFILE`

## Archive

### archive.threads

#### `archive.threads.enabled`

Enable daily archival of old thread packages to external object storage

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__ARCHIVE__THREADS__ENABLED`

#### `archive.threads.age_days`

Archive threads whose last activity is at least this many days old

* **Type:** `int`
* **Default:** `365`
* **Override:** `GENESIS__ARCHIVE__THREADS__AGE_DAYS`

#### `archive.threads.connection_type`

Named connection type used to resolve archive storage credentials

* **Type:** `str`
* **Default:** `"aws"`
* **Options:** `aws`
* **Override:** `GENESIS__ARCHIVE__THREADS__CONNECTION_TYPE`

#### `archive.threads.connection_name`

Named connection used to authenticate archive uploads

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__ARCHIVE__THREADS__CONNECTION_NAME`

#### `archive.threads.bucket`

Destination object-storage bucket for archived thread packages

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__ARCHIVE__THREADS__BUCKET`

#### `archive.threads.path_prefix`

Root path prefix inside the bucket. Thread archives are stored beneath threads/... under this prefix.

* **Type:** `str`
* **Default:** `"genesis/archive"`
* **Override:** `GENESIS__ARCHIVE__THREADS__PATH_PREFIX`

#### `archive.threads.max_threads_per_run`

Maximum number of thread archives to process in a single daily run

* **Type:** `int`
* **Default:** `100`
* **Override:** `GENESIS__ARCHIVE__THREADS__MAX_THREADS_PER_RUN`

## Chat File Uploads

#### `files.max_upload_bytes`

Largest chat upload accepted, in bytes (default 100 MiB). Enforced only where uploads are kept durable in a Unity Catalog volume (a Databricks App); other deployments do not apply this cap, though their server or ingress may limit request size.

* **Type:** `int`
* **Default:** `104857600`
* **Minimum:** `1`
* **Override:** `GENESIS__FILES__MAX_UPLOAD_BYTES`

## Slots

#### `slots.chat_queue_timeout_seconds`

How long a user chat message waits in the queue for an agent slot. -1 = wait indefinitely (default), 0 = fail immediately (no queue), >0 = wait up to this many seconds.

* **Type:** `int`
* **Default:** `-1`
* **Override:** `GENESIS__SLOTS__CHAT_QUEUE_TIMEOUT_SECONDS`
* **Environment default:** `GENESIS_CHAT_QUEUE_TIMEOUT`

#### `slots.chat_cooldown_seconds`

Seconds an agent slot stays reserved after a chat completion finishes, allowing quick follow-up messages without re-queuing. Minimum 0.

* **Type:** `int`
* **Default:** `300`
* **Override:** `GENESIS__SLOTS__CHAT_COOLDOWN_SECONDS`
* **Environment default:** `GENESIS_CHAT_AGENT_SLOT_COOLDOWN`

## Onboarding

#### `onboarding.enabled`

Master switch for one-on-one onboarding. When false, onboarding lock is disabled.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__ONBOARDING__ENABLED`
* **Environment default:** `ONBOARDING_ENABLED`

#### `onboarding.admins_go_through_onboarding`

When true, admin users are also prompted for onboarding (admins may still dismiss).

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ONBOARDING__ADMINS_GO_THROUGH_ONBOARDING`
* **Environment default:** `ONBOARDING_ADMINS_GO_THROUGH`

#### `onboarding.require_existing_users`

When true, users without onboarding state are treated as pending and required to onboard.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__ONBOARDING__REQUIRE_EXISTING_USERS`
* **Environment default:** `ONBOARDING_REQUIRE_EXISTING_USERS`

#### `onboarding.required_topics`

Required onboarding checklist topics. Items may be strings or objects with key/label.

* **Type:** `list`
* **Default:** shown below
* **Override:** `GENESIS__ONBOARDING__REQUIRED_TOPICS`

```json theme={null}
[
  {
    "key": "name_and_language",
    "label": "Confirm your name and preferred language"
  },
  {
    "key": "job_role",
    "label": "What is your job role and responsibility?"
  },
  {
    "key": "data_sources",
    "label": "What data sources/connectors do you need access to?"
  },
  {
    "key": "validated_data_access",
    "label": "Validate at least one valued data target (or log unmet access + concrete plan)"
  }
]
```

#### `onboarding.optional_topics`

Optional onboarding/check-in topics. Items may be strings or objects with key/label.

* **Type:** `list`
* **Default:** shown below
* **Override:** `GENESIS__ONBOARDING__OPTIONAL_TOPICS`

```json theme={null}
[
  {
    "key": "collaboration_preferences",
    "label": "Collaboration preferences"
  },
  {
    "key": "short_term_objectives",
    "label": "Short-term objectives"
  },
  {
    "key": "broader_goals",
    "label": "Broader goals / weekly check-in prompts"
  }
]
```

## Launchpad

#### `launchpad.checklist_enabled`

Master switch for the Launchpad setup checklist and finish-setup indicator

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__LAUNCHPAD__CHECKLIST_ENABLED`

#### `launchpad.checklist_items`

Launchpad setup checklist items; completion is derived from backend state per user. Kinds: database\_connection, git\_connection, first\_thread, connection:\<type>, encryption\_key (shown only on a Snowflake native app, to users who can manage secrets).

* **Type:** `list`
* **Default:** shown below
* **Override:** `GENESIS__LAUNCHPAD__CHECKLIST_ITEMS`

```json theme={null}
[
  {
    "key": "encryption",
    "label": "Set up the encryption key",
    "kind": "encryption_key",
    "mandatory": true
  },
  {
    "key": "database",
    "label": "Connect to your Data Sources",
    "kind": "database_connection",
    "mandatory": true
  },
  {
    "key": "git",
    "label": "Connect to your Code Repositories",
    "kind": "git_connection",
    "mandatory": false
  },
  {
    "key": "first_chat",
    "label": "Chat with Eve",
    "kind": "first_thread",
    "mandatory": false
  }
]
```

## Guardrails

### guardrails.context\_protection

#### `guardrails.context_protection.warning_threshold`

Context usage percentage to trigger warning and moderate compression

* **Type:** `int`
* **Default:** `85`
* **Override:** `GENESIS__GUARDRAILS__CONTEXT_PROTECTION__WARNING_THRESHOLD`
* **Environment default:** `CONTEXT_WARNING_THRESHOLD`

#### `guardrails.context_protection.warning_target`

Target percentage for compression at warning threshold

* **Type:** `int`
* **Default:** `45`
* **Override:** `GENESIS__GUARDRAILS__CONTEXT_PROTECTION__WARNING_TARGET`
* **Environment default:** `CONTEXT_WARNING_TARGET`

#### `guardrails.context_protection.critical_threshold`

Context usage percentage to trigger aggressive compression

* **Type:** `int`
* **Default:** `90`
* **Override:** `GENESIS__GUARDRAILS__CONTEXT_PROTECTION__CRITICAL_THRESHOLD`
* **Environment default:** `CONTEXT_CRITICAL_THRESHOLD`

#### `guardrails.context_protection.critical_target`

Target percentage for aggressive compression at critical threshold

* **Type:** `int`
* **Default:** `30`
* **Override:** `GENESIS__GUARDRAILS__CONTEXT_PROTECTION__CRITICAL_TARGET`
* **Environment default:** `CONTEXT_CRITICAL_TARGET`

#### `guardrails.context_protection.block_threshold`

If usage remains above this after critical compression, block the message

* **Type:** `int`
* **Default:** `95`
* **Override:** `GENESIS__GUARDRAILS__CONTEXT_PROTECTION__BLOCK_THRESHOLD`
* **Environment default:** `CONTEXT_BLOCK_THRESHOLD`

### guardrails.repetition\_guard

#### `guardrails.repetition_guard.enabled`

Enable detection of repeated identical user messages. This does not apply to agent messages or tool calls.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__GUARDRAILS__REPETITION_GUARD__ENABLED`
* **Environment default:** `REPETITION_GUARD_ENABLED`

#### `guardrails.repetition_guard.threshold`

Block after this many strictly consecutive identical user messages. Agent tool-call loop detection uses a separate internal guard.

* **Type:** `int`
* **Default:** `20`
* **Override:** `GENESIS__GUARDRAILS__REPETITION_GUARD__THRESHOLD`
* **Environment default:** `REPETITION_THRESHOLD`

#### `guardrails.repetition_guard.max_tracked_threads`

Maximum user-message threads to track for repetition (LRU eviction)

* **Type:** `int`
* **Default:** `1000`
* **Override:** `GENESIS__GUARDRAILS__REPETITION_GUARD__MAX_TRACKED_THREADS`
* **Environment default:** `REPETITION_MAX_TRACKED_THREADS`

## Flows

### flows.failure\_visibility

#### `flows.failure_visibility.enabled`

Notify operators in-app when an unattended Flow run fails, independent of the Flow's on\_failure mode

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__FLOWS__FAILURE_VISIBILITY__ENABLED`

#### `flows.failure_visibility.unattended_triggers`

Flow run trigger types treated as unattended for failure notification; add 'api' if external automation runs Flows

* **Type:** `list`
* **Default:** `["schedule"]`
* **Override:** `GENESIS__FLOWS__FAILURE_VISIBILITY__UNATTENDED_TRIGGERS`

#### `flows.failure_visibility.first_notify_after_failures`

Consecutive failed Flow runs before the first operator notification

* **Type:** `int`
* **Default:** `1`
* **Override:** `GENESIS__FLOWS__FAILURE_VISIBILITY__FIRST_NOTIFY_AFTER_FAILURES`

#### `flows.failure_visibility.repeat_every_failures`

After the first notification, re-notify every N further consecutive failures

* **Type:** `int`
* **Default:** `10`
* **Override:** `GENESIS__FLOWS__FAILURE_VISIBILITY__REPEAT_EVERY_FAILURES`

#### `flows.failure_visibility.min_seconds_between_notifications`

Hard floor between operator notifications for the same Flow, bounding alert volume for fast-failing Flows; 0 disables the floor

* **Type:** `int`
* **Default:** `3600`
* **Override:** `GENESIS__FLOWS__FAILURE_VISIBILITY__MIN_SECONDS_BETWEEN_NOTIFICATIONS`

## Sandbox Runner

#### `sandbox_runner.enabled`

Master switch for the per-thread Claude Code sandbox thread runner. OFF by default and rollout-gated: when off, no sandbox containers are ever started and no thread routes to the sandbox. GENESIS\_SANDBOX\_RUNNER\_ENABLED opts a deployment in as a default; set GENESIS\_\_SANDBOX\_RUNNER\_\_ENABLED to force it and lock this toggle. Requires bot\_ids to also name at least one bot.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__SANDBOX_RUNNER__ENABLED`
* **Environment default:** `GENESIS_SANDBOX_RUNNER_ENABLED`

#### `sandbox_runner.provision_credentials`

When on (and the runner is enabled), materialize the RBAC-allowed (user, bot) connection credentials into each sandbox container as GENESIS\_CONN\_\* env vars so the agent's own code can connect to data sources directly. RBAC is enforced before any secret is decrypted; the env is injected via docker -e and never written to the agent workspace or transcript. OFF by default. NOTE: this provisions env vars only — running snowsql/dbt CLIs additionally needs the CLIs baked into the image and an egress-permitting network (separate follow-up).

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__SANDBOX_RUNNER__PROVISION_CREDENTIALS`
* **Environment default:** `GENESIS_SANDBOX_RUNNER_PROVISION_CREDENTIALS`

#### `sandbox_runner.bot_ids`

Bot ids whose threads run in the sandbox (Claude Code inside a per-thread container) when the runner is enabled. Empty = no bot uses it even if enabled.

* **Type:** `list`
* **Default:** `[]`
* **Override:** `GENESIS__SANDBOX_RUNNER__BOT_IDS`
* **Environment default:** `GENESIS_SANDBOX_RUNNER_BOT_IDS`

#### `sandbox_runner.image`

Docker image carrying node + the claude CLI for sandbox threads.

* **Type:** `str`
* **Default:** `"genesis-sandbox-claude:latest"`
* **Override:** `GENESIS__SANDBOX_RUNNER__IMAGE`
* **Environment default:** `GENESIS_SANDBOX_RUNNER_IMAGE`

#### `sandbox_runner.model`

Model id passed to the claude CLI. Blank = the CLI's own default.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__SANDBOX_RUNNER__MODEL`
* **Environment default:** `GENESIS_SANDBOX_RUNNER_MODEL`

#### `sandbox_runner.proxy_base_url`

ANTHROPIC\_BASE\_URL exported into the container so the agent's LLM calls route back through the Genesis proxy (the container never holds the org key).

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__SANDBOX_RUNNER__PROXY_BASE_URL`
* **Environment default:** `GENESIS_SANDBOX_RUNNER_PROXY_BASE_URL`

#### `sandbox_runner.network`

Docker --network value for sandbox containers. Blank (default) = Docker's default bridge = OPEN EGRESS: the agent's baked-in CLIs can reach any host the Docker host can. This is intentional — the operator owns the egress boundary and is expected to apply a network policy / egress proxy around the container. Set this to pin a locked-down network (e.g. 'none' plus an egress proxy, or a custom restricted network) without a code change.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__SANDBOX_RUNNER__NETWORK`
* **Environment default:** `GENESIS_SANDBOX_RUNNER_NETWORK`

#### `sandbox_runner.llm_model`

litellm model string the proxy routes to (e.g. bedrock/us.anthropic.claude-sonnet-4-6). When set, the proxy is provider-agnostic instead of forwarding to api.anthropic.com.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__SANDBOX_RUNNER__LLM_MODEL`
* **Environment default:** `GENESIS_SANDBOX_RUNNER_LLM_MODEL`

#### `sandbox_runner.mcp_url`

Genesis MCP endpoint reachable from the container, so the sandbox agent can call governed Genesis tools over MCP.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__SANDBOX_RUNNER__MCP_URL`
* **Environment default:** `GENESIS_SANDBOX_RUNNER_MCP_URL`

#### `sandbox_runner.reap_idle_seconds`

Reap a thread's container after it has been idle this long (seconds). Per-thread volumes are kept, so a reaped thread restarts fast and --resumes with full context.

* **Type:** `float`
* **Default:** `1800.0`
* **Override:** `GENESIS__SANDBOX_RUNNER__REAP_IDLE_SECONDS`
* **Environment default:** `GENESIS_SANDBOX_RUNNER_REAP_IDLE_SECONDS`

#### `sandbox_runner.reap_interval_seconds`

How often the idle-container reaper sweep runs (seconds).

* **Type:** `float`
* **Default:** `300.0`
* **Override:** `GENESIS__SANDBOX_RUNNER__REAP_INTERVAL_SECONDS`
* **Environment default:** `GENESIS_SANDBOX_RUNNER_REAP_INTERVAL_SECONDS`

#### `sandbox_runner.busy_max_idle_seconds`

Hard ceiling (seconds, default 3 hours) on how long a container that is still running processes may survive without a turn. The normal window is reap\_idle\_seconds; a container doing work — a background build, a dev server, a monitor an agent left running — is spared past it, because reaping on turn activity alone kills work nobody asked to stop. This is the backstop that keeps sparing bounded: one wedged process must not pin a container forever. Set \<= 0 to remove the ceiling, which makes a stuck process an unbounded leak. Note the ceiling is measured from the last turn THIS backend process observed, not from the container's true last use: a backend restart re-bases it, granting a running container a fresh window. That is deliberate — the alternative makes every restart a mass-kill of live threads — but it means a deployment that restarts more often than this value will never reach the ceiling.

* **Type:** `float`
* **Default:** `10800.0`
* **Override:** `GENESIS__SANDBOX_RUNNER__BUSY_MAX_IDLE_SECONDS`
* **Environment default:** `GENESIS_SANDBOX_RUNNER_BUSY_MAX_IDLE_SECONDS`

#### `sandbox_runner.volume_gc_idle_seconds`

Reclaim a thread's per-thread volumes after they have been dangling (referenced by no container) this long (seconds; default 7 days). Much larger than the container reap window so a thread has ample time to resume and re-attach its volume. \<= 0 disables volume GC.

* **Type:** `float`
* **Default:** `604800.0`
* **Override:** `GENESIS__SANDBOX_RUNNER__VOLUME_GC_IDLE_SECONDS`
* **Environment default:** `GENESIS_SANDBOX_RUNNER_VOLUME_GC_IDLE_SECONDS`

#### `sandbox_runner.session_store_path`

Durable file mapping each thread to its CLI resume id, so --resume survives a backend restart.

* **Type:** `str`
* **Default:** `"~/.genesis/sandbox_runner_sessions.json"`
* **Override:** `GENESIS__SANDBOX_RUNNER__SESSION_STORE_PATH`
* **Environment default:** `GENESIS_SANDBOX_RUNNER_SESSION_STORE`

#### `sandbox_runner.cpu_request`

CPU reserved for each sandbox, as a Kubernetes quantity ('100m' = a tenth of a core). Kubernetes deducts a request from the node whether or not it is used, and these containers are idle between turns (measured: \~1MiB and one process while idle, since the agent is spawned per turn and exits), so a small request keeps them densely packed. Too small is not free either: it is the floor that survives eviction when a node comes under pressure. Blank leaves the CPU request unset. Ignored by the docker runtime, which has no scheduler to reserve against. Applies to sandboxes created after the change; an existing one keeps its current bounds until it is reaped (reap\_idle\_seconds), because replacing a live sandbox would kill whatever its agent is in the middle of.

* **Type:** `str`
* **Default:** `"100m"`
* **Override:** `GENESIS__SANDBOX_RUNNER__CPU_REQUEST`
* **Environment default:** `GENESIS_SANDBOX_RUNNER_CPU_REQUEST`

#### `sandbox_runner.cpu_limit`

Hard CPU ceiling for each sandbox, as a Kubernetes quantity ('2' = two cores). A limit costs nothing until it is reached, so it can be generous; exceeding it throttles the container rather than killing it. Blank leaves CPU uncapped, which lets one agent burst across every core on the host or node. Applied as --cpus under the docker runtime. Applies to sandboxes created after the change; an existing one keeps its current bounds until it is reaped (reap\_idle\_seconds), because replacing a live sandbox would kill whatever its agent is in the middle of.

* **Type:** `str`
* **Default:** `"2"`
* **Override:** `GENESIS__SANDBOX_RUNNER__CPU_LIMIT`
* **Environment default:** `GENESIS_SANDBOX_RUNNER_CPU_LIMIT`

#### `sandbox_runner.memory_request`

Memory reserved for each sandbox, as a Kubernetes quantity. Same trade-off as cpu\_request: reserved whether used or not, so keep it near the idle footprint plus headroom rather than near the peak. Under the docker runtime this becomes --memory-reservation, a soft limit that applies only when the host is under memory pressure. Blank leaves the memory request unset. Applies to sandboxes created after the change; an existing one keeps its current bounds until it is reaped (reap\_idle\_seconds), because replacing a live sandbox would kill whatever its agent is in the middle of.

* **Type:** `str`
* **Default:** `"256Mi"`
* **Override:** `GENESIS__SANDBOX_RUNNER__MEMORY_REQUEST`
* **Environment default:** `GENESIS_SANDBOX_RUNNER_MEMORY_REQUEST`

#### `sandbox_runner.memory_limit`

Hard memory ceiling for each sandbox, as a Kubernetes quantity. This is the load-bearing bound: memory cannot be throttled, only reclaimed by killing something, so without it a runaway agent drives the host or node into memory pressure and takes neighbours down with it. Exceeding it OOM-kills the sandbox alone, which is the containment we want. A trivial turn was measured at \~140MiB peak, but real data work goes well above that, so raise this rather than leaving it blank. Applied as --memory under the docker runtime. Applies to sandboxes created after the change; an existing one keeps its current bounds until it is reaped (reap\_idle\_seconds), because replacing a live sandbox would kill whatever its agent is in the middle of.

* **Type:** `str`
* **Default:** `"2Gi"`
* **Override:** `GENESIS__SANDBOX_RUNNER__MEMORY_LIMIT`
* **Environment default:** `GENESIS_SANDBOX_RUNNER_MEMORY_LIMIT`

#### `sandbox_runner.runtime`

Which backend executes each per-thread sandbox: 'docker' (default; local dev or any host exposing a Docker daemon) or 'kubernetes' (one Pod per thread via the in-cluster API). A managed cluster that exposes no Docker daemon to workloads — GKE Autopilot blocks the docker socket structurally — must select 'kubernetes'. An unrecognised value falls back to 'docker' so bad config never breaks startup.

* **Type:** `str`
* **Default:** `"docker"`
* **Options:** `docker`, `kubernetes`
* **Override:** `GENESIS__SANDBOX_RUNNER__RUNTIME`
* **Environment default:** `GENESIS_SANDBOX_RUNNER_RUNTIME`

#### `sandbox_runner.k8s_namespace`

Kubernetes runtime only: namespace the per-thread sandbox Pods run in. A dedicated namespace keeps the blast radius off the backend's own namespace and gives the Pods their own ResourceQuota.

* **Type:** `str`
* **Default:** `"genesis-sandbox"`
* **Override:** `GENESIS__SANDBOX_RUNNER__K8S_NAMESPACE`
* **Environment default:** `GENESIS_SANDBOX_RUNNER_K8S_NAMESPACE`

#### `sandbox_runner.k8s_runtime_class`

Kubernetes runtime only: runtimeClassName applied to each sandbox Pod, e.g. 'gvisor' for syscall-level isolation. Blank = the cluster's default runtime class. gVisor is available on GKE Autopilot but not on every cluster, so preflight degrades when it is absent.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__SANDBOX_RUNNER__K8S_RUNTIME_CLASS`
* **Environment default:** `GENESIS_SANDBOX_RUNNER_K8S_RUNTIME_CLASS`

#### `sandbox_runner.k8s_service_account`

Kubernetes runtime only: service account for the per-thread sandbox Pods. Blank = the namespace's default service account. The sandbox Pods need no Kubernetes API access of their own.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__SANDBOX_RUNNER__K8S_SERVICE_ACCOUNT`
* **Environment default:** `GENESIS_SANDBOX_RUNNER_K8S_SERVICE_ACCOUNT`

#### `sandbox_runner.k8s_storage_class`

Kubernetes runtime only: storage class for each thread's home PVC. Blank = the cluster's default storage class.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__SANDBOX_RUNNER__K8S_STORAGE_CLASS`
* **Environment default:** `GENESIS_SANDBOX_RUNNER_K8S_STORAGE_CLASS`

#### `sandbox_runner.k8s_home_volume_size`

Kubernetes runtime only: size of each thread's home PersistentVolumeClaim, as a Kubernetes quantity (e.g. '2Gi').

* **Type:** `str`
* **Default:** `"2Gi"`
* **Override:** `GENESIS__SANDBOX_RUNNER__K8S_HOME_VOLUME_SIZE`
* **Environment default:** `GENESIS_SANDBOX_RUNNER_K8S_HOME_VOLUME_SIZE`

#### `sandbox_runner.k8s_pod_ready_timeout_seconds`

Kubernetes runtime only: how long to wait (seconds) for a per-thread sandbox Pod to become Ready before failing the turn. A ceiling on a legitimately slow start, not the common path: a cold start that must provision a sandboxed (gVisor) node on GKE Autopilot was measured at 169-187s, so a lower value fails turns that would have succeeded. A hopeless Pod (unpullable image, bad config) is still failed immediately by its terminal waiting reason rather than waiting this out.

* **Type:** `float`
* **Default:** `420.0`
* **Override:** `GENESIS__SANDBOX_RUNNER__K8S_POD_READY_TIMEOUT_SECONDS`
* **Environment default:** `GENESIS_SANDBOX_RUNNER_K8S_POD_READY_TIMEOUT_SECONDS`

#### `sandbox_runner.backend_service`

Kubernetes runtime only: name of the backend's own Kubernetes Service, used to build the in-cluster URL the sandbox Pods call back on (the LLM proxy and MCP). Under Kubernetes this replaces the docker 'host.docker.internal' address.

* **Type:** `str`
* **Default:** `"genesis"`
* **Override:** `GENESIS__SANDBOX_RUNNER__BACKEND_SERVICE`
* **Environment default:** `GENESIS_SANDBOX_RUNNER_BACKEND_SERVICE`

## Cli Terminal

#### `cli_terminal.enabled`

Master switch for direct CLI terminal access: a per-user workspace container running Claude Code that a user attaches a real terminal to, using a client on their own machine over the standard Genesis port (scripts/genesis\_cli\_terminal.py, or `genesis login`). ATTACHING is laptop-client only — the browser UI has no terminal for this; what the flag reveals in-product is the admin CLI Workspaces tab in Pulse, which lists, restarts and cancels workspaces and needs view\_sandboxes. OFF by default. Turning it on is not sufficient on its own — a user also needs the use\_cli\_terminal permission on one of their roles. This is a genuine shell inside a container where the agent runs with permission prompts disabled, so grant it deliberately.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__CLI_TERMINAL__ENABLED`
* **Environment default:** `GENESIS_CLI_TERMINAL_ENABLED`

#### `cli_terminal.image`

Container image for a user's CLI workspace. Carries node plus the claude CLI; build it from container/Dockerfile.sandbox-claude.

* **Type:** `str`
* **Default:** `"genesis-sandbox-claude:latest"`
* **Override:** `GENESIS__CLI_TERMINAL__IMAGE`
* **Environment default:** `GENESIS_CLI_TERMINAL_IMAGE`

#### `cli_terminal.image_pull_timeout_seconds`

How long the FIRST attach may take while Docker pulls the workspace image (seconds, default 30 minutes). Separate from the ordinary command timeout because `docker run` performs the pull INSIDE that one call — the -d flag detaches the container, not the download — so a machine without the image cached spends the whole transfer inside a single docker invocation. Measured range for the \~700MB image: 45s on a datacentre network, 53 minutes on a home connection. Too low and a first attach fails with a timeout while the pull was progressing normally, which reads as a broken feature rather than a slow download. Only the container-create call uses this; every other docker command keeps the short timeout, so a genuinely hung daemon is still caught quickly.

* **Type:** `float`
* **Default:** `1800.0`
* **Override:** `GENESIS__CLI_TERMINAL__IMAGE_PULL_TIMEOUT_SECONDS`
* **Environment default:** `GENESIS_CLI_TERMINAL_IMAGE_PULL_TIMEOUT_SECONDS`

#### `cli_terminal.idle_reap_seconds`

Remove a user's workspace container after this long with no terminal attached (default 1 hour). Their volume is kept, so their Claude Code sessions survive and reattaching just costs a few seconds. \<= 0 disables reaping.

* **Type:** `float`
* **Default:** `3600.0`
* **Override:** `GENESIS__CLI_TERMINAL__IDLE_REAP_SECONDS`
* **Environment default:** `GENESIS_CLI_TERMINAL_IDLE_REAP_SECONDS`

#### `cli_terminal.reap_interval_seconds`

How often the idle-workspace sweep runs. Checking every 5 minutes against a 1-hour idle window reaps a workspace within a few minutes of its deadline without a pointless docker call every few seconds. \<= 0 registers no sweep at all, which means nothing ever reclaims a workspace.

* **Type:** `float`
* **Default:** `300.0`
* **Override:** `GENESIS__CLI_TERMINAL__REAP_INTERVAL_SECONDS`
* **Environment default:** `GENESIS_CLI_TERMINAL_REAP_INTERVAL_SECONDS`

#### `cli_terminal.max_workspaces`

Hard ceiling on concurrently-running CLI workspace containers across all users.

* **Type:** `int`
* **Default:** `25`
* **Override:** `GENESIS__CLI_TERMINAL__MAX_WORKSPACES`
* **Environment default:** `GENESIS_CLI_TERMINAL_MAX_WORKSPACES`

#### `cli_terminal.max_sessions_per_workspace`

How many terminal windows one user may have open at once. max\_workspaces bounds containers, not what runs inside them: every distinct session name a client uses creates another PTY, another exec client and another tmux session, and none of those is removed by disconnecting, because sessions outlive their connection by design. Reattaching to a session that already exists is always allowed, so this caps creation without locking anyone out of windows they already have. \<= 0 disables the cap.

* **Type:** `int`
* **Default:** `8`
* **Override:** `GENESIS__CLI_TERMINAL__MAX_SESSIONS_PER_WORKSPACE`
* **Environment default:** `GENESIS_CLI_TERMINAL_MAX_SESSIONS_PER_WORKSPACE`

#### `cli_terminal.cpus`

CPU CEILING per user workspace. Docker's --cpus. On Kubernetes it is NOT set as a limit — CPU is compressible, so a ceiling there buys only CFS throttling on an interactive agent — so this documents the intended maximum while cpu\_request is what the scheduler reserves. A workspace may host several interactive agents at once, which is why it is larger than the per-thread runner's turn-sized request.

* **Type:** `str`
* **Default:** `"2"`
* **Override:** `GENESIS__CLI_TERMINAL__CPUS`
* **Environment default:** `GENESIS_CLI_TERMINAL_CPUS`

#### `cli_terminal.cpu_request`

CPU a workspace RESERVES on Kubernetes, as opposed to the ceiling it may grow into. Ignored by the Docker backend, which has no equivalent. Reserving the full ceiling made every workspace hold 2 CPU while idle, so ten users needed 20 CPU of headroom on a cluster running at a few percent; reserving 500m needs 5. Nothing caps growth above this, so the smaller reservation costs throughput only when the node is genuinely contended.

* **Type:** `str`
* **Default:** `"500m"`
* **Override:** `GENESIS__CLI_TERMINAL__CPU_REQUEST`
* **Environment default:** `GENESIS_CLI_TERMINAL_CPU_REQUEST`

#### `cli_terminal.memory`

Memory CEILING per user WORKSPACE, not per agent: one user gets one workspace, and every terminal session they open (up to max\_sessions\_per\_workspace) runs its own claude inside this one allocation. This is a HARD CAP, not a reservation — memory is not compressible, so a workspace that exceeds it is OOM-killed, and that kills EVERY session the user has open, not just the greedy one. 8g is the interactive-load default (4g was OOM-killed under real use, because a workspace hosts several agents plus the headless browser the agent drives). The memory-backed /dev/shm (shm\_size) shares this ceiling: its used pages are charged against this limit (Kubernetes does not pre-reserve the emptyDir sizeLimit), so shm usage and process memory contend for the 8g and a full 1Gi shm can leave up to 1Gi less for the process. What the scheduler RESERVES is memory\_request, which is smaller: a workspace is guaranteed that much and may grow to this. The value is written for `docker run --memory` and converted to a Kubernetes quantity ("8g" -> "8Gi"). Sizing, per-platform notes and the scheduling traps are in docs/in-pod-coding-agent-sizing.md.

* **Type:** `str`
* **Default:** `"8g"`
* **Override:** `GENESIS__CLI_TERMINAL__MEMORY`
* **Environment default:** `GENESIS_CLI_TERMINAL_MEMORY`

#### `cli_terminal.shm_size`

Kubernetes only: size of the memory-backed /dev/shm mounted into a workspace. The container runtime caps /dev/shm at 64Mi, which is far too small for the headless Chrome the agent drives — the tab dies mid-render — so a memory-backed emptyDir is mounted at /dev/shm at this size instead. IMPORTANT: an emptyDir with medium Memory is charged to the container's memory limit as its pages are used, not pre-reserved, so this is an additional maximum that counts against `memory` only as the shm is populated — an empty shm deducts nothing and a full 1Gi shm reduces available process memory by up to 1Gi of the 8g cap. It is charged to the LIMIT, not to memory\_request, so it does not have to be reserved. Docker units are converted ("1g" -> "1Gi"). Docker's own /dev/shm sizing has no equivalent here, so this has no docker effect.

* **Type:** `str`
* **Default:** `"1Gi"`
* **Override:** `GENESIS__CLI_TERMINAL__SHM_SIZE`
* **Environment default:** `GENESIS_CLI_TERMINAL_SHM_SIZE`

#### `cli_terminal.image_pull_secret`

Name of a docker-registry Secret, in the WORKSPACE namespace, used to pull the workspace image. Kubernetes only. Needed for any private registry: the kubelet pulls the image and holds none of the backend's credentials, so without it a private image fails with ImagePullBackOff while the backend itself started fine — it has a pull secret on its own StatefulSet and this had none. The secret must exist in the workspace namespace rather than the release namespace, because pull secrets are namespaced and workspaces do not run beside the backend. The Helm chart creates it there for you when ecr.enabled is set.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__CLI_TERMINAL__IMAGE_PULL_SECRET`
* **Environment default:** `GENESIS_CLI_TERMINAL_IMAGE_PULL_SECRET`

#### `cli_terminal.memory_request`

Memory a workspace RESERVES on Kubernetes, as opposed to the ceiling it may grow into. Ignored by the Docker backend. Kubernetes uses this for scheduling and for EVICTION RANKING, not as an absolute floor: a workspace using more than its request is evicted before one using less, and under extreme node pressure even a workspace below its request can be evicted. It lowers the risk rather than removing it. It is also what cluster capacity must actually supply: 10 concurrent users need 10 x this, not 10 x memory. Keep it below memory: setting them equal reserves the whole 8g ceiling for every idle workspace, which is what made this mode need a specially sized cluster. The default is half the ceiling because 4g was the previous ceiling and held a real workspace until peak interactive load — it reserves what a workspace typically needs while leaving 8g to grow into. Raising it trades density for protection from a busy neighbour.

* **Type:** `str`
* **Default:** `"4g"`
* **Override:** `GENESIS__CLI_TERMINAL__MEMORY_REQUEST`
* **Environment default:** `GENESIS_CLI_TERMINAL_MEMORY_REQUEST`

#### `cli_terminal.model`

Anthropic model name exported to the workspace as ANTHROPIC\_MODEL, e.g. 'claude-opus-4-5'. Claude Code sizes its context window and decides when to auto-compact from the model it believes it is using; with nothing set it falls back to its own default and calibrates against a model the proxy does not serve, which can make a short conversation report itself as full. This is a LABEL, not a routing choice — the proxy resolves the model that actually serves each call from the thread's provider settings and ignores what the client asked for. Set it to whichever Anthropic model most closely matches the context window of the model really behind the proxy. Blank leaves Claude Code to guess.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__CLI_TERMINAL__MODEL`
* **Environment default:** `GENESIS_CLI_TERMINAL_MODEL`

#### `cli_terminal.agent_id`

Genesis agent that the terminal's MCP tool calls act as. Note no thread is bound: each Claude Code conversation creates and keeps its own Genesis thread, so tool calls stay scoped per conversation and the terminal transcript is never written into a thread.

* **Type:** `str`
* **Default:** `"Eve"`
* **Override:** `GENESIS__CLI_TERMINAL__AGENT_ID`
* **Environment default:** `GENESIS_CLI_TERMINAL_AGENT_ID`

#### `cli_terminal.mcp_url`

Genesis MCP endpoint as the workspace container sees it. Blank derives it from FASTAPI\_HTTP\_PORT via host.docker.internal.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__CLI_TERMINAL__MCP_URL`
* **Environment default:** `GENESIS_CLI_TERMINAL_MCP_URL`

#### `cli_terminal.proxy_base_url`

ANTHROPIC\_BASE\_URL for the workspace, so the agent's LLM calls route back through the Genesis proxy and the real org key never enters the container. Blank derives it from FASTAPI\_HTTP\_PORT.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__CLI_TERMINAL__PROXY_BASE_URL`
* **Environment default:** `GENESIS_CLI_TERMINAL_PROXY_BASE_URL`

#### `cli_terminal.runtime`

Which backend hosts terminal workspaces. 'docker' runs them as containers on a local daemon; 'kubernetes' runs one Pod per user in k8s\_namespace. Mirrors sandbox\_runner.runtime. Anything unrecognised is treated as docker, so a typo cannot silently move workspaces onto the newer backend.

* **Type:** `str`
* **Default:** `"docker"`
* **Options:** `docker`, `kubernetes`
* **Override:** `GENESIS__CLI_TERMINAL__RUNTIME`
* **Environment default:** `GENESIS_CLI_TERMINAL_RUNTIME`

#### `cli_terminal.home_volume_size`

Kubernetes only: size of EACH of the two per-user PersistentVolumeClaims — the home volume carrying CLAUDE\_CONFIG\_DIR and the user's saved conversations, and the work volume holding their files. Both claims are created at this size, so the default of 10Gi allocates 20Gi per user in total; size the namespace's storage quota accordingly. Docker's named volumes are unsized, so this has no docker equivalent.

* **Type:** `str`
* **Default:** `"10Gi"`
* **Override:** `GENESIS__CLI_TERMINAL__HOME_VOLUME_SIZE`
* **Environment default:** `GENESIS_CLI_TERMINAL_HOME_VOLUME_SIZE`

#### `cli_terminal.k8s_namespace`

Kubernetes only: namespace the per-user workspace Pods run in. A dedicated namespace keeps the blast radius off the backend's own and gives the workspaces their own ResourceQuota.

* **Type:** `str`
* **Default:** `"genesis-cli"`
* **Override:** `GENESIS__CLI_TERMINAL__K8S_NAMESPACE`
* **Environment default:** `GENESIS_CLI_TERMINAL_K8S_NAMESPACE`

## UI Features

#### `features.show_beta_ai_providers`

Offer the Beta AI Providers web interface and its Stable/Beta switch. Off redirects Beta links to Stable, including saved browser preferences. Enable explicitly on internal instances with GENESIS\_\_FEATURES\_\_SHOW\_BETA\_AI\_PROVIDERS=true. Shared provider APIs remain available to Stable.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__FEATURES__SHOW_BETA_AI_PROVIDERS`

#### `features.computer_use_enabled`

Offer Computer Use in Genesis Desktop. Off hides its dedicated settings controls and removes the capability from agent discovery and execution, even with saved local consent. On only exposes the feature: the signed-in person's desktop.computer\_use\_enabled opt-in, approved apps and native OS permissions are still required. Changes take effect without restarting Genesis.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__FEATURES__COMPUTER_USE_ENABLED`

#### `features.unified_chrome`

Give the web dashboard the Genesis Desktop window's chrome: a thin top bar with the setup, MCP, help and notification controls, the Genesis mark at the top of the left rail, the account menu at its foot, and the rail, thread list and content panels tiled edge to edge. A deployment whose header shows a custom Branding logo keeps its taller header. Set false to restore the previous web chrome (rounded floating panels under the full-width header). The desktop app always uses its own chrome.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__FEATURES__UNIFIED_CHROME`
* **Environment default:** `GENESIS_UNIFIED_CHROME`

#### `features.presenter_controls_enabled`

Enable the staff-only Presentation mode toggle in the user menu, the presenter demo routes, and presenter-bound Mission starts on this instance.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__FEATURES__PRESENTER_CONTROLS_ENABLED`

#### `features.slack_account_linking_enabled`

Enable user self-service Slack account linking to a canonical Genesis user identity.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__FEATURES__SLACK_ACCOUNT_LINKING_ENABLED`
* **Environment default:** `SLACK_ACCOUNT_LINKING_ENABLED`

#### `features.slack_account_linking_dm_fallback_enabled`

Allow legacy DM code entry (`link <code>`) for Slack account linking during secure-modal rollout.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__FEATURES__SLACK_ACCOUNT_LINKING_DM_FALLBACK_ENABLED`
* **Environment default:** `SLACK_ACCOUNT_LINKING_DM_FALLBACK_ENABLED`

#### `features.hide_manage_context_state_calls`

Hide manage\_context\_state tool-call activity in chat and tool-call UI surfaces.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__FEATURES__HIDE_MANAGE_CONTEXT_STATE_CALLS`
* **Environment default:** `HIDE_MANAGE_CONTEXT_STATE_CALLS`

### features.capture\_browser

#### `features.capture_browser.persistent`

Reuse a single browser across dashboard screenshots instead of launching a new one each time. Significantly speeds up repeated captures.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__FEATURES__CAPTURE_BROWSER__PERSISTENT`
* **Environment default:** `ENABLE_PERSISTENT_CAPTURE_BROWSER`

#### `features.capture_browser.tab_ttl`

How long (in seconds) to keep an inactive dashboard tab open before closing it. Default is 15 minutes.

* **Type:** `int`
* **Default:** `900`
* **Override:** `GENESIS__FEATURES__CAPTURE_BROWSER__TAB_TTL`
* **Environment default:** `CAPTURE_TAB_TTL_SECONDS`

#### `features.show_secrets_panel`

Show the Secrets panel in the Config sidebar (to users who can manage or view secrets). Shown by default; set false to hide it.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__FEATURES__SHOW_SECRETS_PANEL`
* **Environment default:** `SHOW_SECRETS_PANEL`

#### `features.show_estate`

Show the Prover (estate / spec-conformance) area in the sidebar. ON by default — the rollout gate is retired and no Prover-specific environment variable is needed to see the tab. Two supported ways to hide it: write false through the config API (Advanced Settings, or PUT /api/config/advanced/value with path features.show\_estate), which stays editable in the UI; or set the standard GENESIS\_\_FEATURES\_\_SHOW\_ESTATE=false override, which outranks that write and locks the Advanced Settings toggle. Hiding the tab removes navigation only — the estate routes keep answering for a permitted caller. There is deliberately no default\_env\_var of this field's own.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__FEATURES__SHOW_ESTATE`

#### `features.managed_upgrade_panel`

Show the Upgrades page and mount its API on a managed deployment. Off by default and set only by the managed chart's override (GENESIS\_\_FEATURES\_\_MANAGED\_UPGRADE\_PANEL); standalone and unmanaged installs never see the page or its routes. Read once when the app starts.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__FEATURES__MANAGED_UPGRADE_PANEL`

#### `features.skill_revision_tracking`

Enable governed Git revisions for managed skills. Off by default until the skill release policy, audit trail, and thread pinning have been reviewed for this deployment.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__FEATURES__SKILL_REVISION_TRACKING`

#### `features.show_action_review`

Show Action Review in the web client: the Approval rules and Your approval permissions pages under Settings → Configuration, each request's full record at /action-review, and, when Work is off, the Queue as its own sidebar and mobile navigation entry and default-homepage option. Pending approvals are decided in Work → Queue; there is no separate Action Review entry. ON by default. Two supported ways to hide it: write false through the config API (Advanced Settings, or PUT /api/config/advanced/value with path features.show\_action\_review), which stays editable in the UI; or set the standard GENESIS\_\_FEATURES\_\_SHOW\_ACTION\_REVIEW=false override, which outranks that write and locks the Advanced Settings toggle. Only the web surfaces are gated: the Action Review API and in-chat approval cards keep working either way, because governed actions such as CRM merges still require human review.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__FEATURES__SHOW_ACTION_REVIEW`

#### `features.hide_user_default_connection_toggle`

Hide the 'Make this my default connection' controls in the Connections UI, for deployments that do not want per-user default connections. Existing user defaults keep working and stay visible as badges; only the controls to set or clear them are removed.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__FEATURES__HIDE_USER_DEFAULT_CONNECTION_TOGGLE`
* **Environment default:** `HIDE_USER_DEFAULT_CONNECTION_TOGGLE`

#### `features.cost_usage_tracking`

The one switch for all usage recording: per-turn LLM token costs, tool usage and scan spend, written to the local SQLite cost cube. It also feeds Demo Budget and bot stats, not only Costs. Turn it off only as an emergency lever to cut SQLite write contention under heavy concurrent load; Costs then shows recording as off.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__FEATURES__COST_USAGE_TRACKING`

#### `features.cost_accounting`

Deprecated and ignored: nothing reads this key. Costs is on for every install: the /api/costs routes, the Pulse Costs screen, the rollup job and every cost producer run whatever this is set to. The Cost & Usage dataset keeps its instance column (the agent) and adds install\_instance, and /api/config/frontend reports cost\_accounting as true for older clients. The entry stays so that an existing install's stored value, and a saved config carrying it, still validate.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__FEATURES__COST_ACCOUNTING`

## Header Activity Strip

#### `activity_strip.enabled`

Show the activity strip in the web client's header: active users, active threads, active agents, missions running and Context Graph nodes, with a status dot. ON by default. Set false to remove it for everyone; the server then computes no snapshot and records no last actions, and the activity endpoints answer a cheap disabled response. The agent-turn registry still keeps its own bounded in-memory list of recently ended turns (at most 1,000, 10 minutes), which the strip reads when on. Read on every request, so a change applies without a restart; browsers pick it up on their next page load.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ACTIVITY_STRIP__ENABLED`

#### `activity_strip.active_user_window_minutes`

A person counts as an active user for this many minutes after they last sent a message or started a run, as well as while something they started is still running. An open browser tab alone never counts unless count\_page\_activity is on.

* **Type:** `int`
* **Default:** `15`
* **Minimum:** `1`
* **Maximum:** `1440`
* **Override:** `GENESIS__ACTIVITY_STRIP__ACTIVE_USER_WINDOW_MINUTES`

#### `activity_strip.count_page_activity`

Count browsing as acting: a person using Genesis in a browser counts as an active user for page\_activity\_idle\_seconds after their last input on the page (a key press, click, touch, wheel or trackpad scroll, or bringing the tab back into view), even without sending a message; a message still counts for active\_user\_window\_minutes. The open page reports how long ago that input was on the keep-alive heartbeat it already sends (about every 30 seconds); input older than page\_activity\_idle\_seconds, or a tab nobody has touched, never counts. Recorded in memory at most once per person every 30 seconds; nothing is stored and no request is added. Scheduled flows never count. No effect while enabled is false. Read on every heartbeat, so a change applies without a restart.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__ACTIVITY_STRIP__COUNT_PAGE_ACTIVITY`

#### `activity_strip.page_activity_idle_seconds`

With count\_page\_activity on, how long a person's last input on the page keeps them active: a heartbeat counts only when that input was at most this many seconds earlier, and a person who only browsed stops counting this long after their last input, so an open tab left idle stops counting after this long.

* **Type:** `int`
* **Default:** `180`
* **Minimum:** `30`
* **Maximum:** `3600`
* **Override:** `GENESIS__ACTIVITY_STRIP__PAGE_ACTIVITY_IDLE_SECONDS`

#### `activity_strip.recent_turn_seconds`

A thread, and its agent, keeps counting as active for this many seconds after its last agent turn ends, so a turn that starts and ends between two snapshots is still seen. The status dot ignores this: it is green only while work is running. 0 counts running turns only.

* **Type:** `int`
* **Default:** `60`
* **Minimum:** `0`
* **Maximum:** `600`
* **Override:** `GENESIS__ACTIVITY_STRIP__RECENT_TURN_SECONDS`

#### `activity_strip.snapshot_ttl_seconds`

How long one activity snapshot is reused before it is computed again when nothing happens. Every viewer shares the same snapshot, so the server computes the totals at most once per interval however many browsers are open. Activity (a turn starting or ending, a person sending a message or, with count\_page\_activity on, using a page) makes the next request compute it sooner, limited by snapshot\_min\_interval\_seconds.

* **Type:** `int`
* **Default:** `20`
* **Minimum:** `5`
* **Maximum:** `300`
* **Override:** `GENESIS__ACTIVITY_STRIP__SNAPSHOT_TTL_SECONDS`

#### `activity_strip.snapshot_min_interval_seconds`

The shortest time between two activity snapshots when activity makes the current one out of date, so new work shows within this many seconds of the next request while a busy system still computes the totals at most once per interval. Has no effect while nothing happens: the snapshot then lives for snapshot\_ttl\_seconds.

* **Type:** `int`
* **Default:** `2`
* **Minimum:** `1`
* **Maximum:** `60`
* **Override:** `GENESIS__ACTIVITY_STRIP__SNAPSHOT_MIN_INTERVAL_SECONDS`

#### `activity_strip.context_graph_count_ttl_seconds`

How long the Context Graph node count shown in the activity strip is reused before it is read again from the context graph.

* **Type:** `int`
* **Default:** `300`
* **Minimum:** `30`
* **Maximum:** `86400`
* **Override:** `GENESIS__ACTIVITY_STRIP__CONTEXT_GRAPH_COUNT_TTL_SECONDS`

## Rooms

#### `rooms.bot_id`

Agent every room thread is created under. It is half the (bot\_id, thread\_id) storage key, so it is effectively write-once: change it and every existing room becomes unreachable -- not listed, not readable, and its buffered mail never drains -- until it is changed back. Set it before the first room is created.

* **Type:** `str`
* **Default:** `"Eve"`
* **Override:** `GENESIS__ROOMS__BOT_ID`

#### `rooms.sweep_interval_seconds`

Seconds between passes that drain buffered room messages into their thread. 0 disables the sweep.

* **Type:** `int`
* **Default:** `10`
* **Override:** `GENESIS__ROOMS__SWEEP_INTERVAL_SECONDS`

#### `rooms.default_access`

Access a new room gets when its creator does not choose: public (anyone may join) or private (a current member must approve a join request, or invite the newcomer). Rooms created before this setting existed stay public.

* **Type:** `str`
* **Default:** `"public"`
* **Options:** `public`, `private`
* **Override:** `GENESIS__ROOMS__DEFAULT_ACCESS`

#### `rooms.default_listing`

Listing a new room gets when its creator does not choose: listed (shown in the room directory) or unlisted (shown to its members only; anyone else needs the room's name to ask to join). Rooms created before this setting existed stay listed.

* **Type:** `str`
* **Default:** `"listed"`
* **Options:** `listed`, `unlisted`
* **Override:** `GENESIS__ROOMS__DEFAULT_LISTING`

#### `rooms.agent_tools_enabled`

Let Genesis agents take part in rooms with the rooms\_action tool: list, create, join, invite, leave, read and post, with files. Off: the tool is hidden and refused.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__ROOMS__AGENT_TOOLS_ENABLED`

#### `rooms.max_subscribed_threads`

Most Genesis threads that may follow (subscribe to) one room and be woken by its messages. A further subscribe is refused with a plain message; that thread can still read and post in the room on demand.

* **Type:** `int`
* **Default:** `8`
* **Minimum:** `1`
* **Override:** `GENESIS__ROOMS__MAX_SUBSCRIBED_THREADS`

## Background Jobs

### jobs.default\_model\_probe

#### `jobs.default_model_probe.enabled`

Probe a changed Genesis default model with one tiny completion before assigning it to a tier that follows Genesis defaults. A refused default leaves the tier on its last working model as deferred\_default and re-probes it; off assigns changed defaults on restart without a probe.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__JOBS__DEFAULT_MODEL_PROBE__ENABLED`

#### `jobs.default_model_probe.interval_seconds`

Seconds between ticks of the default-model prober. Each tick probes only tiers that are due: a tier whose new default has not been verified yet, a retry after an inconclusive probe, or a deferred tier whose re-probe interval has passed. The first tick runs as the server starts.

* **Type:** `int`
* **Default:** `300`
* **Minimum:** `60`
* **Maximum:** `86400`
* **Override:** `GENESIS__JOBS__DEFAULT_MODEL_PROBE__INTERVAL_SECONDS`

#### `jobs.default_model_probe.reprobe_interval_seconds`

Seconds between re-probes of a deferred\_default tier's target model (also the longest wait between retries after inconclusive probes). Deferred tiers are also re-probed once after every restart.

* **Type:** `int`
* **Default:** `86400`
* **Minimum:** `3600`
* **Maximum:** `2592000`
* **Override:** `GENESIS__JOBS__DEFAULT_MODEL_PROBE__REPROBE_INTERVAL_SECONDS`

### jobs.notification\_cleanup

#### `jobs.notification_cleanup.failure_threshold`

Consecutive failed passes of the hourly expired-notification cleanup after which /api/health reports the server degraded, naming the cleanup as the reason. A single failure is logged and retried at the next pass; it never stops the server. Where the liveness probe reads /api/health (the managed Helm chart), a degraded server is restarted gracefully. A successful pass clears the degradation. Read at each failed pass.

* **Type:** `int`
* **Default:** `3`
* **Minimum:** `1`
* **Override:** `GENESIS__JOBS__NOTIFICATION_CLEANUP__FAILURE_THRESHOLD`

### jobs.dataset\_cleanup

#### `jobs.dataset_cleanup.startup_delay_seconds`

Seconds after server start before the first dataset cleanup pass (expired query-cache datasets and stale snapshots). Later passes follow every GENESIS\_DATASET\_CLEANUP\_INTERVAL\_S. Read at scheduler registration.

* **Type:** `int`
* **Default:** `120`
* **Minimum:** `0`
* **Maximum:** `3600`
* **Override:** `GENESIS__JOBS__DATASET_CLEANUP__STARTUP_DELAY_SECONDS`

#### `jobs.dataset_cleanup.batch_size`

Most expired datasets, and most stale snapshots, one cleanup batch deletes. A pass runs batches back to back, off the event loop, until nothing eligible is left or pass\_budget\_seconds runs out. Read at the start of each pass.

* **Type:** `int`
* **Default:** `100`
* **Minimum:** `1`
* **Maximum:** `1000`
* **Override:** `GENESIS__JOBS__DATASET_CLEANUP__BATCH_SIZE`

#### `jobs.dataset_cleanup.pass_budget_seconds`

Wall-clock budget for one dataset cleanup pass. The batch that crosses it finishes and no new batch starts; what is left waits for the next pass. Read at the start of each pass.

* **Type:** `int`
* **Default:** `600`
* **Minimum:** `10`
* **Maximum:** `3600`
* **Override:** `GENESIS__JOBS__DATASET_CLEANUP__PASS_BUDGET_SECONDS`

### jobs.room\_sweep

#### `jobs.room_sweep.enabled`

Drain buffered agent-room messages into their room thread once no turn is running

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__JOBS__ROOM_SWEEP__ENABLED`

### jobs.project\_evidence\_recorder

#### `jobs.project_evidence_recorder.enabled`

Record each copy the server filed under a migration project on that project, once a minute: check the copy's table and write one note by the server, so Landed shows the work whether or not the chat recorded it. Costs one indexed metadata read a minute while idle; each check can start the copy's SQL warehouse. Off: the job stays paused and filed copies wait, losing nothing. A change takes effect at the next restart (or resume the job from Pulse).

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__JOBS__PROJECT_EVIDENCE_RECORDER__ENABLED`

#### `jobs.scheduler_interval_seconds`

Legacy scheduler sweep interval in seconds

* **Type:** `int`
* **Default:** `5`
* **Override:** `GENESIS__JOBS__SCHEDULER_INTERVAL_SECONDS`
* **Environment default:** `SCHEDULER_SECONDS_INTERVAL`

#### `jobs.missed_one_time_job_grace_seconds`

How late a scheduled one-time job may still run when its time passed while Genesis was not running (Genesis Desktop closed, a server restart). Within this many seconds of its run time it runs once as soon as the scheduler starts; later than that it is kept, paused and marked missed in its history, for the person to run or reschedule. It is never deleted. A job's own misfire\_grace\_time, when set, takes precedence. 0 runs none late. Read at scheduler start.

* **Type:** `int`
* **Default:** `3600`
* **Minimum:** `0`
* **Override:** `GENESIS__JOBS__MISSED_ONE_TIME_JOB_GRACE_SECONDS`

### jobs.flow\_interrupted\_copy\_target\_check

#### `jobs.flow_interrupted_copy_target_check.enabled`

After a restart, count what interrupted Flow copy steps left in their target tables and add it to the step summary (runs only while such steps are waiting)

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__JOBS__FLOW_INTERRUPTED_COPY_TARGET_CHECK__ENABLED`

#### `jobs.flow_interrupted_copy_target_check.interval_seconds`

Seconds between interrupted-copy target check passes; 0 or less disables it

* **Type:** `int`
* **Default:** `120`
* **Override:** `GENESIS__JOBS__FLOW_INTERRUPTED_COPY_TARGET_CHECK__INTERVAL_SECONDS`

### jobs.managed\_skill\_release\_poll

#### `jobs.managed_skill_release_poll.enabled`

Check managed skill sources for new release tags on a schedule. Each pass asks every enabled skill source's Git remote for its tags. A Fixed release source is never changed: the pass only flags a newer release on its Managed Sources row and raises an alert if its pinned tag moved or was deleted. A Follow latest release source is upgraded to the newest release as an audited system change, under the same production policy as an administrator's change. Off: the job stays paused and nothing is checked. Does nothing while features.skill\_revision\_tracking is off. A change takes effect at the next restart (or resume the job from Pulse).

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__JOBS__MANAGED_SKILL_RELEASE_POLL__ENABLED`

#### `jobs.managed_skill_release_poll.interval_seconds`

Seconds between managed skill release checks (default 15 minutes). Each pass makes one request to each skill source's Git host, so a short interval multiplies that traffic. A change takes effect at the next restart.

* **Type:** `int`
* **Default:** `900`
* **Minimum:** `60`
* **Maximum:** `86400`
* **Override:** `GENESIS__JOBS__MANAGED_SKILL_RELEASE_POLL__INTERVAL_SECONDS`

### jobs.managed\_source\_auto\_sync

#### `jobs.managed_source_auto_sync.enabled`

Sync managed sources that have 'sync automatically' switched on, on a schedule. Each pass asks the Git host of every such source whether its tags, tracked branch or default branch moved, and runs the same sync the Sync button runs when they did. A source without the switch is never contacted, so this does nothing until an administrator opts a source in. Off: the job stays paused and no source is synced automatically. A change takes effect at the next restart (or resume the job from Pulse).

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__JOBS__MANAGED_SOURCE_AUTO_SYNC__ENABLED`

#### `jobs.managed_source_auto_sync.interval_seconds`

Seconds between automatic managed source sync passes (default 5 minutes). Each pass makes one request to the Git host of every source with 'sync automatically' on, so a short interval multiplies that traffic. A change takes effect at the next restart.

* **Type:** `int`
* **Default:** `300`
* **Minimum:** `60`
* **Maximum:** `86400`
* **Override:** `GENESIS__JOBS__MANAGED_SOURCE_AUTO_SYNC__INTERVAL_SECONDS`

### jobs.flow\_failure\_notifications

#### `jobs.flow_failure_notifications.enabled`

Enable durable delivery of notify\_thread Flow failures to the trusted Slack alerts channel

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__JOBS__FLOW_FAILURE_NOTIFICATIONS__ENABLED`

#### `jobs.flow_failure_notifications.interval_seconds`

Seconds between Flow failure notification outbox delivery passes

* **Type:** `int`
* **Default:** `15`
* **Override:** `GENESIS__JOBS__FLOW_FAILURE_NOTIFICATIONS__INTERVAL_SECONDS`

#### `jobs.flow_failure_notifications.batch_size`

Maximum Flow failure notifications claimed per delivery pass

* **Type:** `int`
* **Default:** `20`
* **Override:** `GENESIS__JOBS__FLOW_FAILURE_NOTIFICATIONS__BATCH_SIZE`

#### `jobs.flow_failure_notifications.claim_timeout_seconds`

Seconds before an abandoned Flow failure notification claim is recovered

* **Type:** `int`
* **Default:** `120`
* **Override:** `GENESIS__JOBS__FLOW_FAILURE_NOTIFICATIONS__CLAIM_TIMEOUT_SECONDS`

#### `jobs.flow_failure_notifications.max_attempts`

Maximum Slack delivery attempts before a Flow failure notification is exhausted

* **Type:** `int`
* **Default:** `5`
* **Override:** `GENESIS__JOBS__FLOW_FAILURE_NOTIFICATIONS__MAX_ATTEMPTS`

#### `jobs.flow_failure_notifications.base_backoff_seconds`

Base seconds for exponential Flow failure notification retry backoff

* **Type:** `int`
* **Default:** `15`
* **Override:** `GENESIS__JOBS__FLOW_FAILURE_NOTIFICATIONS__BASE_BACKOFF_SECONDS`

#### `jobs.flow_failure_notifications.target_bot_id`

Genesis bot targeted by delivered Flow failure alerts

* **Type:** `str`
* **Default:** `"Eve"`
* **Override:** `GENESIS__JOBS__FLOW_FAILURE_NOTIFICATIONS__TARGET_BOT_ID`

### jobs.twin\_harvest

#### `jobs.twin_harvest.enabled`

Master opt-in switch for Twin harvesting, including scheduled scans and per-connection automatic triggers

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__JOBS__TWIN_HARVEST__ENABLED`

### jobs.billing\_close

#### `jobs.billing_close.interval_seconds`

Seconds between billing monthly close passes. Each pass locks the usage counts of every month whose grace period (three days after month end) has passed; late data becomes an adjustment in the next close. Set to 0 or less to avoid registering the job

* **Type:** `int`
* **Default:** `3600`
* **Override:** `GENESIS__JOBS__BILLING_CLOSE__INTERVAL_SECONDS`

### jobs.twin\_scan\_cost\_sync

#### `jobs.twin_scan_cost_sync.enabled`

Run the periodic sync of Twin scan spend into the cost & usage cube (SCAN\_USAGE\_FACTS). On by default; each pass reads a bounded window that reaches back no further than the cost cutover

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__JOBS__TWIN_SCAN_COST_SYNC__ENABLED`

#### `jobs.twin_scan_cost_sync.interval_seconds`

Seconds between Twin scan-cost sync passes; set to 0 or less to avoid registering the job

* **Type:** `int`
* **Default:** `900`
* **Override:** `GENESIS__JOBS__TWIN_SCAN_COST_SYNC__INTERVAL_SECONDS`

### jobs.cost\_accounting\_rollup

#### `jobs.cost_accounting_rollup.enabled`

Deprecated and ignored: nothing reads this key. The cost accounting rollup job (hourly/daily rollups, execution summaries, guarded raw-fact retention) runs on every install; set jobs.cost\_accounting\_rollup.interval\_seconds to 0 or less to stop it. The entry stays so that an existing install's stored value, and a saved config carrying it, still validate.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__JOBS__COST_ACCOUNTING_ROLLUP__ENABLED`

#### `jobs.cost_accounting_rollup.interval_seconds`

Seconds between cost accounting rollup passes; set to 0 or less to avoid registering the job. While the rollup is off (here, or paused), retention seals and expires only days the rollup fully read; cost facts it never read are kept rather than deleted unsummarized, so raw cost facts grow until the rollup runs again. Deliberate: spend is never lost or counted twice

* **Type:** `int`
* **Default:** `300`
* **Override:** `GENESIS__JOBS__COST_ACCOUNTING_ROLLUP__INTERVAL_SECONDS`

#### `jobs.cost_accounting_rollup.batch_size`

Cost facts read per rollup batch; each batch commits its derived rows and cursor together

* **Type:** `int`
* **Default:** `5000`
* **Override:** `GENESIS__JOBS__COST_ACCOUNTING_ROLLUP__BATCH_SIZE`

#### `jobs.cost_accounting_rollup.max_day_facts`

Maximum facts in one complete open day derived by ordinary refresh, independent of cursor page size; ordinary refresh never derives a larger day, which holds its source's rollup cursor until a staged rederivation rebuilds it

* **Type:** `int`
* **Default:** `5000`
* **Override:** `GENESIS__JOBS__COST_ACCOUNTING_ROLLUP__MAX_DAY_FACTS`

#### `jobs.cost_accounting_rollup.overlap_hours`

Hours before each source's rollup cursor that every pass re-reads, so late facts and still-open Twin buckets correct their rollups; also how long after its last fact an execution closes

* **Type:** `int`
* **Default:** `3`
* **Override:** `GENESIS__JOBS__COST_ACCOUNTING_ROLLUP__OVERLAP_HOURS`

### jobs.cost\_cube\_v2\_retention

#### `jobs.cost_cube_v2_retention.enabled`

Run the daily cost cube retention cleanup (90 days). Always registered; each firing stands down only while the cost\_accounting\_rollup job is registered and active (not paused), which then owns retention. With the rollup job off, paused, unregistered or unsupported on the substrate, this job runs the cleanup

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__JOBS__COST_CUBE_V2_RETENTION__ENABLED`

### jobs.demo\_mission\_cleanup

#### `jobs.demo_mission_cleanup.enabled`

Enable deletion of inactive, explicitly owned missions carrying demo:disposable; demo:protected always wins

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__JOBS__DEMO_MISSION_CLEANUP__ENABLED`

#### `jobs.demo_mission_cleanup.interval_seconds`

Seconds between disposable demo mission cleanup passes; set to 0 or less to avoid registering the job

* **Type:** `int`
* **Default:** `300`
* **Override:** `GENESIS__JOBS__DEMO_MISSION_CLEANUP__INTERVAL_SECONDS`

#### `jobs.demo_mission_cleanup.max_age_minutes`

Minimum updated\_at inactivity in minutes before a terminal/inactive disposable demo mission is eligible for deletion

* **Type:** `int`
* **Default:** `25`
* **Override:** `GENESIS__JOBS__DEMO_MISSION_CLEANUP__MAX_AGE_MINUTES`

#### `jobs.demo_mission_cleanup.max_deletions_per_run`

Maximum inactive, explicitly owned disposable demo missions deleted in one cleanup pass

* **Type:** `int`
* **Default:** `50`
* **Override:** `GENESIS__JOBS__DEMO_MISSION_CLEANUP__MAX_DELETIONS_PER_RUN`

#### `jobs.demo_mission_cleanup.dry_run`

Report eligible disposable demo missions without deleting them

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__JOBS__DEMO_MISSION_CLEANUP__DRY_RUN`

### jobs.demo\_readiness\_monitor

#### `jobs.demo_readiness_monitor.enabled`

Enable recurring full-stack readiness probes for the dedicated demo environment

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__JOBS__DEMO_READINESS_MONITOR__ENABLED`

#### `jobs.demo_readiness_monitor.interval_seconds`

Seconds between dedicated demo readiness probes; set to 0 or less to avoid registering the job

* **Type:** `int`
* **Default:** `300`
* **Override:** `GENESIS__JOBS__DEMO_READINESS_MONITOR__INTERVAL_SECONDS`

#### `jobs.demo_readiness_monitor.base_url`

Internal Genesis service URL used by the recurring demo readiness monitor

* **Type:** `str`
* **Default:** `"http://127.0.0.1:8080"`
* **Override:** `GENESIS__JOBS__DEMO_READINESS_MONITOR__BASE_URL`

#### `jobs.demo_readiness_monitor.timeout_seconds`

Per-request timeout for demo readiness dependency probes and alert delivery

* **Type:** `int`
* **Default:** `30`
* **Override:** `GENESIS__JOBS__DEMO_READINESS_MONITOR__TIMEOUT_SECONDS`

#### `jobs.demo_readiness_monitor.alert_webhook_url`

Secret reference resolving to the HTTPS webhook that receives failed demo readiness alerts

* **Type:** `str`
* **Default:** `null`
* **Override:** `GENESIS__JOBS__DEMO_READINESS_MONITOR__ALERT_WEBHOOK_URL`
* **Secret**

### jobs.harvester

#### `jobs.harvester.enabled`

Enable the opt-in harvester background job

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__JOBS__HARVESTER__ENABLED`

#### `jobs.harvester.auto_harvest`

Enable automatic data harvesting

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__JOBS__HARVESTER__AUTO_HARVEST`

#### `jobs.harvester.watchdog_enabled`

Enable the opt-in harvester watchdog background job

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__JOBS__HARVESTER__WATCHDOG_ENABLED`

#### `jobs.harvester.refresh_seconds`

Harvester refresh interval in seconds

* **Type:** `int`
* **Default:** `300`
* **Override:** `GENESIS__JOBS__HARVESTER__REFRESH_SECONDS`
* **Environment default:** `HARVESTER_REFRESH_SECONDS`

#### `jobs.harvester.circuit_breaker_threshold`

Number of consecutive failures before circuit breaker trips

* **Type:** `int`
* **Default:** `5`
* **Override:** `GENESIS__JOBS__HARVESTER__CIRCUIT_BREAKER_THRESHOLD`
* **Environment default:** `HARVESTER_CIRCUIT_BREAKER_THRESHOLD`

#### `jobs.harvester.max_cache_size`

Maximum number of entries in harvester prompt cache

* **Type:** `int`
* **Default:** `1000`
* **Override:** `GENESIS__JOBS__HARVESTER__MAX_CACHE_SIZE`
* **Environment default:** `HARVESTER_MAX_CACHE_SIZE`

### jobs.todo

#### `jobs.todo.enabled`

Enable project todo background job

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__JOBS__TODO__ENABLED`

#### `jobs.todo.concurrency`

Concurrency level for todo job processing

* **Type:** `int`
* **Default:** `3`
* **Override:** `GENESIS__JOBS__TODO__CONCURRENCY`
* **Environment default:** `TODO_JOB_CONCURRENCY`

#### `jobs.todo.disable_nudging`

Disable todo nudging reminders

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__JOBS__TODO__DISABLE_NUDGING`
* **Environment default:** `DISABLE_TODO_NUDGING`

### jobs.dbt\_cloud

#### `jobs.dbt_cloud.enabled`

Enable dbt Cloud background job

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__JOBS__DBT_CLOUD__ENABLED`

### jobs.child\_process\_supervisor

#### `jobs.child_process_supervisor.enabled`

In a Databricks App, respawn a persistent MCP server (scheduler, lineage) or the Slack worker that has exited. Registered only in a Databricks App

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__JOBS__CHILD_PROCESS_SUPERVISOR__ENABLED`

#### `jobs.child_process_supervisor.interval_seconds`

Seconds between child-process liveness checks; set to 0 or less to avoid registering the job

* **Type:** `int`
* **Default:** `30`
* **Override:** `GENESIS__JOBS__CHILD_PROCESS_SUPERVISOR__INTERVAL_SECONDS`

#### `jobs.child_process_supervisor.max_restarts`

Most restarts of one child within restart\_window\_seconds; past it the child is left down and logged. 0 never restarts

* **Type:** `int`
* **Default:** `5`
* **Override:** `GENESIS__JOBS__CHILD_PROCESS_SUPERVISOR__MAX_RESTARTS`

#### `jobs.child_process_supervisor.restart_window_seconds`

Sliding window, in seconds, the restart budget is counted over (minimum 60)

* **Type:** `int`
* **Default:** `3600`
* **Minimum:** `60`
* **Override:** `GENESIS__JOBS__CHILD_PROCESS_SUPERVISOR__RESTART_WINDOW_SECONDS`

### jobs.sandbox\_monitor

#### `jobs.sandbox_monitor.enabled`

Enable sandbox timeout monitor job

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__JOBS__SANDBOX_MONITOR__ENABLED`

#### `jobs.sandbox_monitor.dry_run`

When true, report timeout candidates without stopping/deleting

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__JOBS__SANDBOX_MONITOR__DRY_RUN`

#### `jobs.sandbox_monitor.sleep_seconds`

Sandbox monitor run interval in seconds

* **Type:** `int`
* **Default:** `60`
* **Override:** `GENESIS__JOBS__SANDBOX_MONITOR__SLEEP_SECONDS`

#### `jobs.sandbox_monitor.default_idle_timeout_minutes`

Fallback idle timeout when a session does not define one

* **Type:** `int`
* **Default:** `120`
* **Override:** `GENESIS__JOBS__SANDBOX_MONITOR__DEFAULT_IDLE_TIMEOUT_MINUTES`

#### `jobs.sandbox_monitor.default_max_lifetime_minutes`

Fallback max lifetime when a session does not define one

* **Type:** `int`
* **Default:** `480`
* **Override:** `GENESIS__JOBS__SANDBOX_MONITOR__DEFAULT_MAX_LIFETIME_MINUTES`

#### `jobs.sandbox_monitor.max_deletions_per_run`

Safety limit on stop/deletion actions per monitor run

* **Type:** `int`
* **Default:** `20`
* **Override:** `GENESIS__JOBS__SANDBOX_MONITOR__MAX_DELETIONS_PER_RUN`

#### `jobs.sandbox_monitor.enforce_eks`

Apply timeout enforcement to EKS/K8s sessions

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__JOBS__SANDBOX_MONITOR__ENFORCE_EKS`

#### `jobs.sandbox_monitor.enforce_local`

Apply timeout enforcement to local Docker sessions

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__JOBS__SANDBOX_MONITOR__ENFORCE_LOCAL`

#### `jobs.sandbox_monitor.enforce_railway`

Apply timeout enforcement to Railway sessions

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__JOBS__SANDBOX_MONITOR__ENFORCE_RAILWAY`

#### `jobs.sandbox_monitor.enforce_azure`

Apply timeout enforcement to Azure Container Instances sessions

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__JOBS__SANDBOX_MONITOR__ENFORCE_AZURE`

#### `jobs.sandbox_monitor.eks_namespace`

K8s namespace used for EKS cleanup passes

* **Type:** `str`
* **Default:** `"genesis-sandbox"`
* **Override:** `GENESIS__JOBS__SANDBOX_MONITOR__EKS_NAMESPACE`

#### `jobs.sandbox_monitor.pending_older_than_minutes`

Delete pending pods older than this many minutes during EKS cleanup

* **Type:** `int`
* **Default:** `15`
* **Override:** `GENESIS__JOBS__SANDBOX_MONITOR__PENDING_OLDER_THAN_MINUTES`

#### `jobs.sandbox_monitor.delete_orphan_running`

Allow deleting running pods without a runtime session mapping

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__JOBS__SANDBOX_MONITOR__DELETE_ORPHAN_RUNNING`

#### `jobs.sandbox_monitor.running_orphan_older_than_minutes`

Only delete running orphan pods older than this many minutes

* **Type:** `int`
* **Default:** `240`
* **Override:** `GENESIS__JOBS__SANDBOX_MONITOR__RUNNING_ORPHAN_OLDER_THAN_MINUTES`

### jobs.dormant\_thread\_review

#### `jobs.dormant_thread_review.enabled`

Enable the dormant thread autonomous review scheduler

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__JOBS__DORMANT_THREAD_REVIEW__ENABLED`

#### `jobs.dormant_thread_review.dry_run`

Scan and review threads without creating enhancement reports

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__JOBS__DORMANT_THREAD_REVIEW__DRY_RUN`

#### `jobs.dormant_thread_review.create_drafts`

Create draft Genesis enhancement reports from accepted reviews

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__JOBS__DORMANT_THREAD_REVIEW__CREATE_DRAFTS`

#### `jobs.dormant_thread_review.autosubmit_enabled`

Reserved for future autosubmit; disabled in the initial build

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__JOBS__DORMANT_THREAD_REVIEW__AUTOSUBMIT_ENABLED`

#### `jobs.dormant_thread_review.interval_minutes`

Dormant thread review scheduler interval in minutes

* **Type:** `int`
* **Default:** `15`
* **Override:** `GENESIS__JOBS__DORMANT_THREAD_REVIEW__INTERVAL_MINUTES`

#### `jobs.dormant_thread_review.dormant_after_minutes`

Minimum idle time before a thread can be reviewed

* **Type:** `int`
* **Default:** `60`
* **Override:** `GENESIS__JOBS__DORMANT_THREAD_REVIEW__DORMANT_AFTER_MINUTES`

#### `jobs.dormant_thread_review.scan_lookback_days`

Only consider threads with activity within this many days; set 0 for all history

* **Type:** `int`
* **Default:** `7`
* **Override:** `GENESIS__JOBS__DORMANT_THREAD_REVIEW__SCAN_LOOKBACK_DAYS`

#### `jobs.dormant_thread_review.min_assistant_messages`

Minimum assistant messages required before review

* **Type:** `int`
* **Default:** `5`
* **Override:** `GENESIS__JOBS__DORMANT_THREAD_REVIEW__MIN_ASSISTANT_MESSAGES`

#### `jobs.dormant_thread_review.min_tool_calls`

Minimum tool calls or tool outputs required before review

* **Type:** `int`
* **Default:** `2`
* **Override:** `GENESIS__JOBS__DORMANT_THREAD_REVIEW__MIN_TOOL_CALLS`

#### `jobs.dormant_thread_review.min_new_assistant_messages_after_review`

New assistant messages required before re-review

* **Type:** `int`
* **Default:** `5`
* **Override:** `GENESIS__JOBS__DORMANT_THREAD_REVIEW__MIN_NEW_ASSISTANT_MESSAGES_AFTER_REVIEW`

#### `jobs.dormant_thread_review.max_threads_scanned_per_run`

Maximum thread metadata rows to inspect for the initial testing batch

* **Type:** `int`
* **Default:** `20`
* **Override:** `GENESIS__JOBS__DORMANT_THREAD_REVIEW__MAX_THREADS_SCANNED_PER_RUN`

#### `jobs.dormant_thread_review.max_threads_per_run`

Maximum eligible thread windows to review sequentially

* **Type:** `int`
* **Default:** `20`
* **Override:** `GENESIS__JOBS__DORMANT_THREAD_REVIEW__MAX_THREADS_PER_RUN`

#### `jobs.dormant_thread_review.max_reports_per_thread`

Maximum reports created per reviewed thread window

* **Type:** `int`
* **Default:** `1`
* **Override:** `GENESIS__JOBS__DORMANT_THREAD_REVIEW__MAX_REPORTS_PER_THREAD`

#### `jobs.dormant_thread_review.review_timeout_seconds`

Target timeout for hidden review LLM calls

* **Type:** `int`
* **Default:** `90`
* **Override:** `GENESIS__JOBS__DORMANT_THREAD_REVIEW__REVIEW_TIMEOUT_SECONDS`

#### `jobs.dormant_thread_review.reservation_timeout_minutes`

Age after which reserved review windows can be retried

* **Type:** `int`
* **Default:** `30`
* **Override:** `GENESIS__JOBS__DORMANT_THREAD_REVIEW__RESERVATION_TIMEOUT_MINUTES`

#### `jobs.dormant_thread_review.model_tier`

Model tier used for hidden dormant thread reviews

* **Type:** `str`
* **Default:** `"fast"`
* **Options:** `nano`, `fast`, `main`, `frontier`
* **Override:** `GENESIS__JOBS__DORMANT_THREAD_REVIEW__MODEL_TIER`

### jobs.agent\_review\_classifier

#### `jobs.agent_review_classifier.enabled`

Enable the scheduled agent-review turn classifier job (requires agent\_review\.enabled)

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__JOBS__AGENT_REVIEW_CLASSIFIER__ENABLED`

#### `jobs.agent_review_classifier.interval_minutes`

Agent-review classifier scheduler interval in minutes

* **Type:** `int`
* **Default:** `15`
* **Override:** `GENESIS__JOBS__AGENT_REVIEW_CLASSIFIER__INTERVAL_MINUTES`

#### `jobs.agent_review_classifier.dormant_after_minutes`

Quiet time after which a thread's ungraded span is classified and its trailing task settles

* **Type:** `int`
* **Default:** `60`
* **Override:** `GENESIS__JOBS__AGENT_REVIEW_CLASSIFIER__DORMANT_AFTER_MINUTES`

#### `jobs.agent_review_classifier.min_new_turns_incremental`

Ungraded user turns that trigger an incremental pass on a still-active thread

* **Type:** `int`
* **Default:** `8`
* **Override:** `GENESIS__JOBS__AGENT_REVIEW_CLASSIFIER__MIN_NEW_TURNS_INCREMENTAL`

#### `jobs.agent_review_classifier.scan_lookback_days`

Only consider threads with activity within this many days; set 0 for all history

* **Type:** `int`
* **Default:** `7`
* **Override:** `GENESIS__JOBS__AGENT_REVIEW_CLASSIFIER__SCAN_LOOKBACK_DAYS`

#### `jobs.agent_review_classifier.min_assistant_messages`

Minimum assistant messages required before a thread is classified

* **Type:** `int`
* **Default:** `3`
* **Override:** `GENESIS__JOBS__AGENT_REVIEW_CLASSIFIER__MIN_ASSISTANT_MESSAGES`

#### `jobs.agent_review_classifier.max_threads_per_run`

Maximum threads classified per scheduled tick. The same budget separately bounds settlement-only re-derivation attempts, which cost no model spend

* **Type:** `int`
* **Default:** `20`
* **Override:** `GENESIS__JOBS__AGENT_REVIEW_CLASSIFIER__MAX_THREADS_PER_RUN`

## Cost Accounting

#### `cost_accounting.legacy_rows_belong_to_this_instance`

Deprecated and ignored: nothing reads this key. Costs counts only facts recorded after this install's cost cutover, so facts written before it are never assigned to an instance, rolled up or served, whatever this is set to. The entry stays so that an existing install's stored value, and a saved config carrying it, still validate.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__COST_ACCOUNTING__LEGACY_ROWS_BELONG_TO_THIS_INSTANCE`

## Code Scan

#### `code_scan.policy`

Instance-wide policy for the code-scanning PUSH GATE. 'off' refuses nothing. 'opt\_in' gates the repositories enabled individually. 'forced' gates every repository and removes the per-repository choice. Under 'opt\_in' and 'forced' a push of an unscanned revision is refused — the check is that the code was examined, never what the scan found. This governs enforcement only: scanning on request, through the panel or the snyk\_action tool, is available whenever a Snyk connection is configured, and is deliberately not gated so a user can check code before deciding to enforce anything.

* **Type:** `str`
* **Default:** `"off"`
* **Options:** `off`, `opt_in`, `forced`
* **Override:** `GENESIS__CODE_SCAN__POLICY`

#### `code_scan.connection`

Name of the shared Snyk connection used when a repository names none of its own (e.g. 'snyk.shared'). Blank means repositories must each name one.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__CODE_SCAN__CONNECTION`

#### `code_scan.timeout_seconds`

Seconds before a single Snyk product scan is abandoned. A timed-out scan is recorded as failed, never as clean.

* **Type:** `int`
* **Default:** `600`
* **Override:** `GENESIS__CODE_SCAN__TIMEOUT_SECONDS`

#### `code_scan.retained_scans_per_repo`

How many scanned revisions to keep per repository before pruning the oldest. Results are stored under the repository's .git directory, one set per revision.

* **Type:** `int`
* **Default:** `20`
* **Override:** `GENESIS__CODE_SCAN__RETAINED_SCANS_PER_REPO`

#### `code_scan.snyk_cli_path`

Path to the Snyk CLI binary. The default resolves it from PATH, where the container image installs it.

* **Type:** `str`
* **Default:** `"snyk"`
* **Override:** `GENESIS__CODE_SCAN__SNYK_CLI_PATH`

## Code Scan Repo

#### `code_scan_repo`

Opaque per-object store of per-repository code-scan settings, one row per repo\_id, each holding an 'enabled' flag and an optional 'connection' name. Read via the ConfigAccessor; never descended by the config snapshot loader. Kept out of the repository working tree so Genesis settings are never committed into a customer's repository.

* **Type:** `dict`
* **Default:** `{}`
* **Override:** `GENESIS__CODE_SCAN_REPO`

## Agent Review

#### `agent_review.enabled`

Enable agent-review analysis (classifier routes, backfill, scorecard). Explicit message feedback remains available while analysis is off

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__AGENT_REVIEW__ENABLED`

#### `agent_review.model_tier`

Model tier used for agent-review turn classification

* **Type:** `str`
* **Default:** `"fast"`
* **Options:** `nano`, `fast`, `main`, `frontier`
* **Override:** `GENESIS__AGENT_REVIEW__MODEL_TIER`

### agent\_review\.steering\_patterns

#### `agent_review.steering_patterns.enabled`

Mine recurring steering-correction patterns into candidate learnings as a post-pass of the agent-review classifier job (requires agent\_review\.enabled)

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__AGENT_REVIEW__STEERING_PATTERNS__ENABLED`

#### `agent_review.steering_patterns.min_recurrence`

Steering corrections sharing one (bot, workflow type, anchor) group required before a candidate learning is proposed

* **Type:** `int`
* **Default:** `3`
* **Override:** `GENESIS__AGENT_REVIEW__STEERING_PATTERNS__MIN_RECURRENCE`

#### `agent_review.steering_patterns.window_days`

Lookback window in days for steering-pattern mining

* **Type:** `int`
* **Default:** `30`
* **Override:** `GENESIS__AGENT_REVIEW__STEERING_PATTERNS__WINDOW_DAYS`

### agent\_review\.learning\_deltas

#### `agent_review.learning_deltas.horizon_days`

Days before/after an adoption compared by the learning-delta report

* **Type:** `int`
* **Default:** `14`
* **Override:** `GENESIS__AGENT_REVIEW__LEARNING_DELTAS__HORIZON_DAYS`

#### `agent_review.learning_deltas.min_tasks_per_window`

Minimum settled tasks per window before a learning delta reports rates instead of insufficient\_data

* **Type:** `int`
* **Default:** `5`
* **Override:** `GENESIS__AGENT_REVIEW__LEARNING_DELTAS__MIN_TASKS_PER_WINDOW`

### agent\_review\.feedback\_to\_agents

#### `agent_review.feedback_to_agents.enabled`

Inject the filtered per-agent AGENT REVIEW NOTES block into prompts (behavioral steering patterns only; off means prompts are byte-identical)

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__AGENT_REVIEW__FEEDBACK_TO_AGENTS__ENABLED`

### agent\_review\.grading

#### `agent_review.grading.enabled`

Enable agent grading with review cycles, weakness tracking, levels, promotions, and year-end reports (requires agent\_review\.enabled). Advisory-only; off means the feature is absent

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__AGENT_REVIEW__GRADING__ENABLED`

### agent\_review\.grading.cycle

#### `agent_review.grading.cycle.length`

Review cycle length; monthly/quarterly are calendar-aligned UTC, custom rolls from anchor\_date

* **Type:** `str`
* **Default:** `"monthly"`
* **Options:** `monthly`, `quarterly`, `custom`
* **Override:** `GENESIS__AGENT_REVIEW__GRADING__CYCLE__LENGTH`

#### `agent_review.grading.cycle.custom_days`

Cycle length in days when cycle.length is custom

* **Type:** `int`
* **Default:** `30`
* **Override:** `GENESIS__AGENT_REVIEW__GRADING__CYCLE__CUSTOM_DAYS`

#### `agent_review.grading.cycle.anchor_date`

Anchor date (YYYY-MM-DD) custom cycles roll from; empty means the grading feature-enable date

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__AGENT_REVIEW__GRADING__CYCLE__ANCHOR_DATE`

### agent\_review\.grading.weakness

#### `agent_review.grading.weakness.escalate_after_cycles`

Recurring cycles at which an open weakness escalates

* **Type:** `int`
* **Default:** `2`
* **Override:** `GENESIS__AGENT_REVIEW__GRADING__WEAKNESS__ESCALATE_AFTER_CYCLES`

#### `agent_review.grading.weakness.resolve_after_cycles`

Consecutive clean cycles after which a weakness resolves (purely observational)

* **Type:** `int`
* **Default:** `2`
* **Override:** `GENESIS__AGENT_REVIEW__GRADING__WEAKNESS__RESOLVE_AFTER_CYCLES`

### agent\_review\.grading.feedback

#### `agent_review.grading.feedback.min_feedback_count`

Feedback verdicts required before a feedback score is measurable; below it the level criterion is SKIPPED, never blocking

* **Type:** `int`
* **Default:** `5`
* **Override:** `GENESIS__AGENT_REVIEW__GRADING__FEEDBACK__MIN_FEEDBACK_COUNT`

### agent\_review\.grading.levels

### agent\_review\.grading.levels.l1

#### `agent_review.grading.levels.l1.name`

Display name for level L1

* **Type:** `str`
* **Default:** `"Junior"`
* **Override:** `GENESIS__AGENT_REVIEW__GRADING__LEVELS__L1__NAME`

### agent\_review\.grading.levels.l2

#### `agent_review.grading.levels.l2.name`

Display name for level L2

* **Type:** `str`
* **Default:** `"Associate"`
* **Override:** `GENESIS__AGENT_REVIEW__GRADING__LEVELS__L2__NAME`

#### `agent_review.grading.levels.l2.min_tasks`

Minimum settled tasks over the sustain window for an L2 nomination

* **Type:** `int`
* **Default:** `30`
* **Override:** `GENESIS__AGENT_REVIEW__GRADING__LEVELS__L2__MIN_TASKS`

#### `agent_review.grading.levels.l2.min_first_shot_rate`

Minimum full-policy first-shot rate held over each sustain cycle for L2

* **Type:** `float`
* **Default:** `0.5`
* **Override:** `GENESIS__AGENT_REVIEW__GRADING__LEVELS__L2__MIN_FIRST_SHOT_RATE`

#### `agent_review.grading.levels.l2.max_steering_per_task`

Maximum steering turns per task held over each sustain cycle for L2

* **Type:** `float`
* **Default:** `0.5`
* **Override:** `GENESIS__AGENT_REVIEW__GRADING__LEVELS__L2__MAX_STEERING_PER_TASK`

#### `agent_review.grading.levels.l2.min_feedback_score`

Minimum feedback score (positive/(positive+negative)) for L2

* **Type:** `float`
* **Default:** `0.7`
* **Override:** `GENESIS__AGENT_REVIEW__GRADING__LEVELS__L2__MIN_FEEDBACK_SCORE`

#### `agent_review.grading.levels.l2.sustain_cycles`

Consecutive closed cycles over which the L2 rates must hold

* **Type:** `int`
* **Default:** `2`
* **Override:** `GENESIS__AGENT_REVIEW__GRADING__LEVELS__L2__SUSTAIN_CYCLES`

### agent\_review\.grading.levels.l3

#### `agent_review.grading.levels.l3.name`

Display name for level L3

* **Type:** `str`
* **Default:** `"Specialist"`
* **Override:** `GENESIS__AGENT_REVIEW__GRADING__LEVELS__L3__NAME`

#### `agent_review.grading.levels.l3.min_tasks`

Minimum settled tasks over the sustain window for an L3 nomination

* **Type:** `int`
* **Default:** `75`
* **Override:** `GENESIS__AGENT_REVIEW__GRADING__LEVELS__L3__MIN_TASKS`

#### `agent_review.grading.levels.l3.min_first_shot_rate`

Minimum full-policy first-shot rate held over each sustain cycle for L3

* **Type:** `float`
* **Default:** `0.65`
* **Override:** `GENESIS__AGENT_REVIEW__GRADING__LEVELS__L3__MIN_FIRST_SHOT_RATE`

#### `agent_review.grading.levels.l3.max_steering_per_task`

Maximum steering turns per task held over each sustain cycle for L3

* **Type:** `float`
* **Default:** `0.3`
* **Override:** `GENESIS__AGENT_REVIEW__GRADING__LEVELS__L3__MAX_STEERING_PER_TASK`

#### `agent_review.grading.levels.l3.min_feedback_score`

Minimum feedback score (positive/(positive+negative)) for L3

* **Type:** `float`
* **Default:** `0.8`
* **Override:** `GENESIS__AGENT_REVIEW__GRADING__LEVELS__L3__MIN_FEEDBACK_SCORE`

#### `agent_review.grading.levels.l3.sustain_cycles`

Consecutive closed cycles over which the L3 rates must hold

* **Type:** `int`
* **Default:** `2`
* **Override:** `GENESIS__AGENT_REVIEW__GRADING__LEVELS__L3__SUSTAIN_CYCLES`

### agent\_review\.grading.levels.l4

#### `agent_review.grading.levels.l4.name`

Display name for level L4

* **Type:** `str`
* **Default:** `"Senior"`
* **Override:** `GENESIS__AGENT_REVIEW__GRADING__LEVELS__L4__NAME`

#### `agent_review.grading.levels.l4.min_tasks`

Minimum settled tasks over the sustain window for an L4 nomination

* **Type:** `int`
* **Default:** `150`
* **Override:** `GENESIS__AGENT_REVIEW__GRADING__LEVELS__L4__MIN_TASKS`

#### `agent_review.grading.levels.l4.min_first_shot_rate`

Minimum full-policy first-shot rate held over each sustain cycle for L4

* **Type:** `float`
* **Default:** `0.8`
* **Override:** `GENESIS__AGENT_REVIEW__GRADING__LEVELS__L4__MIN_FIRST_SHOT_RATE`

#### `agent_review.grading.levels.l4.max_steering_per_task`

Maximum steering turns per task held over each sustain cycle for L4

* **Type:** `float`
* **Default:** `0.15`
* **Override:** `GENESIS__AGENT_REVIEW__GRADING__LEVELS__L4__MAX_STEERING_PER_TASK`

#### `agent_review.grading.levels.l4.min_feedback_score`

Minimum feedback score (positive/(positive+negative)) for L4

* **Type:** `float`
* **Default:** `0.9`
* **Override:** `GENESIS__AGENT_REVIEW__GRADING__LEVELS__L4__MIN_FEEDBACK_SCORE`

#### `agent_review.grading.levels.l4.sustain_cycles`

Consecutive closed cycles over which the L4 rates must hold

* **Type:** `int`
* **Default:** `3`
* **Override:** `GENESIS__AGENT_REVIEW__GRADING__LEVELS__L4__SUSTAIN_CYCLES`

## Knowledge Base

#### `knowledge.enabled`

Enable knowledge base features

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__KNOWLEDGE__ENABLED`
* **Environment default:** `USE_KNOWLEDGE`

#### `knowledge.retrieval_count`

Number of knowledge entries to retrieve

* **Type:** `int`
* **Default:** `5`
* **Override:** `GENESIS__KNOWLEDGE__RETRIEVAL_COUNT`
* **Environment default:** `LAST_K_KNOWLEDGE`

## WebSocket

#### `websocket.connection_timeout`

Connection idle timeout in seconds

* **Type:** `int`
* **Default:** `900`
* **Override:** `GENESIS__WEBSOCKET__CONNECTION_TIMEOUT`
* **Environment default:** `WEBSOCKET_CONNECTION_TIMEOUT`

#### `websocket.stream_completion_timeout`

Timeout for waiting for stream completion signal in seconds

* **Type:** `int`
* **Default:** `3600`
* **Override:** `GENESIS__WEBSOCKET__STREAM_COMPLETION_TIMEOUT`
* **Environment default:** `WEBSOCKET_STREAM_COMPLETION_TIMEOUT`

#### `websocket.max_subscriptions`

Maximum simultaneous subscriptions per connection

* **Type:** `int`
* **Default:** `500`
* **Override:** `GENESIS__WEBSOCKET__MAX_SUBSCRIPTIONS`
* **Environment default:** `WEBSOCKET_MAX_SUBSCRIPTIONS`

#### `websocket.max_streams`

Maximum simultaneous streams per connection

* **Type:** `int`
* **Default:** `50`
* **Override:** `GENESIS__WEBSOCKET__MAX_STREAMS`
* **Environment default:** `WEBSOCKET_MAX_STREAMS`

## Metrics

#### `metrics.mode`

Metrics backend type: DISABLED, LOGS, SQL, or BRIDGE

* **Type:** `str`
* **Default:** `"BRIDGE"`
* **Options:** `DISABLED`, `LOGS`, `SQL`, `BRIDGE`
* **Override:** `GENESIS__METRICS__MODE`

#### `metrics.destination`

Database URL for SQL metrics (required when type is SQL or BRIDGE)

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__METRICS__DESTINATION`

#### `metrics.report_interval_s`

How often to export metrics to destination, in seconds

* **Type:** `int`
* **Default:** `30`
* **Override:** `GENESIS__METRICS__REPORT_INTERVAL_S`

#### `metrics.bridge_url`

Metrics bridge API URL (required when type is BRIDGE). Requires restart to take effect

* **Type:** `str`
* **Default:** `"https://stats.genesiscomputing.ai"`
* **Override:** `GENESIS__METRICS__BRIDGE_URL`

#### `metrics.bridge_api_key`

JWT API key for metrics bridge authentication. Requires restart to take effect

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__METRICS__BRIDGE_API_KEY`
* **Secret**

#### `metrics.bridge_upload_frequency_s`

How often to upload metrics to the bridge in seconds (default 1 hour)

* **Type:** `int`
* **Default:** `3600`
* **Override:** `GENESIS__METRICS__BRIDGE_UPLOAD_FREQUENCY_S`

#### `metrics.bridge_upload_batch_size`

Maximum number of metrics per upload batch

* **Type:** `int`
* **Default:** `1000`
* **Override:** `GENESIS__METRICS__BRIDGE_UPLOAD_BATCH_SIZE`

#### `metrics.deployment_id`

Managed deployment ID added to each SQL-backed metric record (SQL and BRIDGE modes; not LOGS or OTLP output) as attributes.deployment\_id; empty adds nothing. Set by the control-plane installer for managed installs. Requires restart to take effect

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__METRICS__DEPLOYMENT_ID`

#### `metrics.diagnostics_upload_enabled`

Also upload diagnostic metrics (LLM calls and tokens, messages, slots, agent steps) to the metrics bridge. Billing usage counts are always kept locally and uploaded whenever the bridge is on; diagnostics are off by default (always on for hosted Try Me instances). Requires restart to take effect

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__METRICS__DIAGNOSTICS_UPLOAD_ENABLED`

## Observability

### observability.tracing

#### `observability.tracing.enabled`

Enable OpenTelemetry tracing

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__OBSERVABILITY__TRACING__ENABLED`
* **Environment default:** `OTEL_TRACING_ENABLED`

#### `observability.tracing.endpoint`

OTLP endpoint URL for trace export

* **Type:** `str`
* **Default:** `"http://localhost:4317"`
* **Override:** `GENESIS__OBSERVABILITY__TRACING__ENDPOINT`
* **Environment default:** `OTEL_EXPORTER_OTLP_ENDPOINT`

#### `observability.tracing.headers`

Authorization headers for OTLP exporter

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OBSERVABILITY__TRACING__HEADERS`
* **Environment default:** `OTEL_EXPORTER_OTLP_HEADERS`

#### `observability.tracing.console_export`

Enable console export when OTLP endpoint is unavailable

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__OBSERVABILITY__TRACING__CONSOLE_EXPORT`
* **Environment default:** `OTEL_CONSOLE_EXPORT`

### observability.metrics

#### `observability.metrics.enabled`

Enable OpenTelemetry metrics push to an external OTLP endpoint (in addition to any local SQL/BRIDGE pipeline configured under metrics.\*)

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__OBSERVABILITY__METRICS__ENABLED`
* **Environment default:** `OTEL_METRICS_ENABLED`

#### `observability.metrics.endpoint`

OTLP endpoint URL for metrics export. Falls back to OTEL\_EXPORTER\_OTLP\_ENDPOINT if unset.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OBSERVABILITY__METRICS__ENDPOINT`
* **Environment default:** `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT`

#### `observability.metrics.protocol`

OTLP transport for metrics export: grpc (default, port 4317) or http (port 4318).

* **Type:** `str`
* **Default:** `"grpc"`
* **Options:** `grpc`, `http`
* **Override:** `GENESIS__OBSERVABILITY__METRICS__PROTOCOL`
* **Environment default:** `OTEL_EXPORTER_OTLP_METRICS_PROTOCOL`

#### `observability.metrics.headers`

Authorization/API-key headers for OTLP metrics exporter (W3C format: key1=value1,key2=value2).

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OBSERVABILITY__METRICS__HEADERS`
* **Startup environment variable:** `OTEL_EXPORTER_OTLP_METRICS_HEADERS`
* **Secret**

#### `observability.metrics.export_interval_s`

How often to push metrics to the OTLP endpoint, in seconds

* **Type:** `int`
* **Default:** `30`
* **Override:** `GENESIS__OBSERVABILITY__METRICS__EXPORT_INTERVAL_S`

### observability.langfuse

#### `observability.langfuse.public_key`

Langfuse public key for observability

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OBSERVABILITY__LANGFUSE__PUBLIC_KEY`
* **Environment default:** `LANGFUSE_PUBLIC_KEY`

#### `observability.langfuse.secret_key`

Langfuse secret key for observability

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OBSERVABILITY__LANGFUSE__SECRET_KEY`
* **Startup environment variable:** `LANGFUSE_SECRET_KEY`
* **Secret**

#### `observability.langfuse.host`

Langfuse host URL

* **Type:** `str`
* **Default:** `"https://cloud.langfuse.com"`
* **Override:** `GENESIS__OBSERVABILITY__LANGFUSE__HOST`
* **Environment default:** `LANGFUSE_HOST`

### observability.loop\_stall\_dump

#### `observability.loop_stall_dump.enabled`

Dump all Python thread stacks to stderr when the FastAPI event loop stops heartbeating

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__OBSERVABILITY__LOOP_STALL_DUMP__ENABLED`

#### `observability.loop_stall_dump.stall_seconds`

Seconds without an event-loop monitor heartbeat before dumping all thread stacks to stderr

* **Type:** `int`
* **Default:** `30`
* **Override:** `GENESIS__OBSERVABILITY__LOOP_STALL_DUMP__STALL_SECONDS`

### observability.pressure\_sampler

#### `observability.pressure_sampler.enabled`

Enable opt-in logging of Linux pressure stall information (PSI) for CPU, I/O, and memory

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__OBSERVABILITY__PRESSURE_SAMPLER__ENABLED`

#### `observability.pressure_sampler.interval_seconds`

How often to log Linux pressure stall information, in seconds

* **Type:** `int`
* **Default:** `60`
* **Override:** `GENESIS__OBSERVABILITY__PRESSURE_SAMPLER__INTERVAL_SECONDS`

### observability.loop\_lag

#### `observability.loop_lag.enabled`

Master toggle for all loop-lag diagnostic instrumentation

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__OBSERVABILITY__LOOP_LAG__ENABLED`
* **Environment default:** `LOOP_LAG_DIAGNOSTICS_ENABLED`

#### `observability.loop_lag.monitor_interval_s`

How often the event-loop lag monitor checks for lag (seconds)

* **Type:** `float`
* **Default:** `10.0`
* **Override:** `GENESIS__OBSERVABILITY__LOOP_LAG__MONITOR_INTERVAL_S`
* **Environment default:** `LOOP_MONITOR_INTERVAL`

#### `observability.loop_lag.slow_callback_threshold_s`

asyncio slow-callback detection threshold in seconds (0 to disable)

* **Type:** `float`
* **Default:** `0.25`
* **Override:** `GENESIS__OBSERVABILITY__LOOP_LAG__SLOW_CALLBACK_THRESHOLD_S`
* **Environment default:** `ASYNCIO_SLOW_CALLBACK_THRESHOLD`

#### `observability.loop_lag.thread_snapshot_enabled`

Capture thread stack snapshots when lag events start

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__OBSERVABILITY__LOOP_LAG__THREAD_SNAPSHOT_ENABLED`
* **Environment default:** `LOOP_LAG_SNAPSHOT_ENABLED`

#### `observability.loop_lag.thread_snapshot_interval_s`

Minimum seconds between thread snapshots (throttle)

* **Type:** `float`
* **Default:** `30.0`
* **Override:** `GENESIS__OBSERVABILITY__LOOP_LAG__THREAD_SNAPSHOT_INTERVAL_S`

#### `observability.loop_lag.hotpath_timing_enabled`

Enable hot-path timing instrumentation (WS broadcasts, serialization, microapp status)

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__OBSERVABILITY__LOOP_LAG__HOTPATH_TIMING_ENABLED`

#### `observability.loop_lag.hotpath_info_threshold_ms`

Operations slower than this threshold are logged at INFO level (milliseconds)

* **Type:** `int`
* **Default:** `100`
* **Override:** `GENESIS__OBSERVABILITY__LOOP_LAG__HOTPATH_INFO_THRESHOLD_MS`

#### `observability.loop_lag.hotpath_warn_threshold_ms`

Operations slower than this threshold are logged at WARNING level (milliseconds)

* **Type:** `int`
* **Default:** `500`
* **Override:** `GENESIS__OBSERVABILITY__LOOP_LAG__HOTPATH_WARN_THRESHOLD_MS`

### observability.thread\_budget

#### `observability.thread_budget.max_active_threads`

Thread budget: when a loop-lag event finds more live threads than this, the server logs one THREAD\_BUDGET\_EXCEEDED warning per process. A warning signal only; nothing is enforced. Read at call time.

* **Type:** `int`
* **Default:** `50`
* **Minimum:** `1`
* **Override:** `GENESIS__OBSERVABILITY__THREAD_BUDGET__MAX_ACTIVE_THREADS`
* **Environment default:** `GENESIS_THREAD_BUDGET`

### observability.memory\_monitor

#### `observability.memory_monitor.mem_trace`

Enable the background memory monitor (RSS / cgroup trajectory / per-type leak suspects). Safe to leave on under memory pressure (no tracemalloc). Set via config so it can be enabled on SPCS without a container env-var/spec change (takes effect on restart).

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__OBSERVABILITY__MEMORY_MONITOR__MEM_TRACE`
* **Environment default:** `GENESIS_MEM_TRACE`

#### `observability.memory_monitor.mem_trace_tracemalloc`

Also enable tracemalloc allocation tracking inside the memory monitor. Inflates RSS -- opt-in for deliberate allocation attribution only.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__OBSERVABILITY__MEMORY_MONITOR__MEM_TRACE_TRACEMALLOC`
* **Environment default:** `GENESIS_MEM_TRACE_TRACEMALLOC`

## OAuth Provider Bootstrap

### oauth\_providers.databricks

#### `oauth_providers.databricks.client_id`

Databricks OAuth client ID (set via Config UI, not env var)

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__DATABRICKS__CLIENT_ID`

#### `oauth_providers.databricks.client_secret`

Databricks OAuth client secret reference/value

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__DATABRICKS__CLIENT_SECRET`
* **Secret**

#### `oauth_providers.databricks.authorization_url`

Databricks OAuth authorization URL (supports \{host} template)

* **Type:** `str`
* **Default:** `"https://{host}/oidc/v1/authorize"`
* **Override:** `GENESIS__OAUTH_PROVIDERS__DATABRICKS__AUTHORIZATION_URL`

#### `oauth_providers.databricks.token_url`

Databricks OAuth token URL (supports \{host} template)

* **Type:** `str`
* **Default:** `"https://{host}/oidc/v1/token"`
* **Override:** `GENESIS__OAUTH_PROVIDERS__DATABRICKS__TOKEN_URL`

#### `oauth_providers.databricks.scopes`

Databricks OAuth scopes requested during user consent

* **Type:** `list`
* **Default:** `["all-apis", "offline_access"]`
* **Override:** `GENESIS__OAUTH_PROVIDERS__DATABRICKS__SCOPES`

#### `oauth_providers.databricks.guide_base_url`

Saved helper base URL for Databricks OAuth setup guidance

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__DATABRICKS__GUIDE_BASE_URL`

#### `oauth_providers.databricks.guide_connection_name`

Saved helper connection name for Databricks OAuth setup guidance

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__DATABRICKS__GUIDE_CONNECTION_NAME`

### oauth\_providers.snowflake

#### `oauth_providers.snowflake.client_id`

Snowflake OAuth client ID (set via Config UI, not env var)

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__SNOWFLAKE__CLIENT_ID`

#### `oauth_providers.snowflake.client_secret`

Snowflake OAuth client secret reference/value

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__SNOWFLAKE__CLIENT_SECRET`
* **Secret**

#### `oauth_providers.snowflake.authorization_url`

Snowflake OAuth authorization URL (supports \{account} template)

* **Type:** `str`
* **Default:** `"https://{account}/oauth/authorize"`
* **Override:** `GENESIS__OAUTH_PROVIDERS__SNOWFLAKE__AUTHORIZATION_URL`

#### `oauth_providers.snowflake.token_url`

Snowflake OAuth token URL (supports \{account} template)

* **Type:** `str`
* **Default:** `"https://{account}/oauth/token-request"`
* **Override:** `GENESIS__OAUTH_PROVIDERS__SNOWFLAKE__TOKEN_URL`

#### `oauth_providers.snowflake.scopes`

Snowflake OAuth scopes requested during user consent

* **Type:** `list`
* **Default:** `[]`
* **Override:** `GENESIS__OAUTH_PROVIDERS__SNOWFLAKE__SCOPES`

#### `oauth_providers.snowflake.guide_base_url`

Saved helper base URL for Snowflake OAuth setup guidance

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__SNOWFLAKE__GUIDE_BASE_URL`

#### `oauth_providers.snowflake.guide_connection_name`

Saved helper connection name for Snowflake OAuth setup guidance

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__SNOWFLAKE__GUIDE_CONNECTION_NAME`

### oauth\_providers.github

#### `oauth_providers.github.client_id`

GitHub OAuth client ID (set via Config UI, not env var)

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__GITHUB__CLIENT_ID`

#### `oauth_providers.github.client_secret`

GitHub OAuth client secret reference/value

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__GITHUB__CLIENT_SECRET`
* **Secret**

#### `oauth_providers.github.authorization_url`

GitHub OAuth authorization URL

* **Type:** `str`
* **Default:** `"https://github.com/login/oauth/authorize"`
* **Override:** `GENESIS__OAUTH_PROVIDERS__GITHUB__AUTHORIZATION_URL`

#### `oauth_providers.github.token_url`

GitHub OAuth token URL

* **Type:** `str`
* **Default:** `"https://github.com/login/oauth/access_token"`
* **Override:** `GENESIS__OAUTH_PROVIDERS__GITHUB__TOKEN_URL`

#### `oauth_providers.github.scopes`

GitHub OAuth scopes requested during user consent

* **Type:** `list`
* **Default:** `["read:user"]`
* **Override:** `GENESIS__OAUTH_PROVIDERS__GITHUB__SCOPES`

#### `oauth_providers.github.guide_base_url`

Saved helper base URL for GitHub OAuth setup guidance

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__GITHUB__GUIDE_BASE_URL`

#### `oauth_providers.github.guide_connection_name`

Saved helper connection name for GitHub OAuth setup guidance

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__GITHUB__GUIDE_CONNECTION_NAME`

### oauth\_providers.gitlab

#### `oauth_providers.gitlab.client_id`

GitLab OAuth client ID (set via Config UI, not env var)

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__GITLAB__CLIENT_ID`

#### `oauth_providers.gitlab.client_secret`

GitLab OAuth client secret reference/value

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__GITLAB__CLIENT_SECRET`
* **Secret**

#### `oauth_providers.gitlab.authorization_url`

GitLab OAuth authorization URL

* **Type:** `str`
* **Default:** `"https://gitlab.com/oauth/authorize"`
* **Override:** `GENESIS__OAUTH_PROVIDERS__GITLAB__AUTHORIZATION_URL`

#### `oauth_providers.gitlab.token_url`

GitLab OAuth token URL

* **Type:** `str`
* **Default:** `"https://gitlab.com/oauth/token"`
* **Override:** `GENESIS__OAUTH_PROVIDERS__GITLAB__TOKEN_URL`

#### `oauth_providers.gitlab.scopes`

GitLab OAuth scopes requested during user consent

* **Type:** `list`
* **Default:** `["read_user", "api"]`
* **Override:** `GENESIS__OAUTH_PROVIDERS__GITLAB__SCOPES`

#### `oauth_providers.gitlab.guide_base_url`

Saved helper base URL for GitLab OAuth setup guidance

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__GITLAB__GUIDE_BASE_URL`

#### `oauth_providers.gitlab.guide_connection_name`

Saved helper connection name for GitLab OAuth setup guidance

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__GITLAB__GUIDE_CONNECTION_NAME`

### oauth\_providers.jira

#### `oauth_providers.jira.client_id`

Jira OAuth client ID (set via Config UI, not env var)

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__JIRA__CLIENT_ID`

#### `oauth_providers.jira.client_secret`

Jira OAuth client secret reference/value

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__JIRA__CLIENT_SECRET`
* **Secret**

#### `oauth_providers.jira.authorization_url`

Jira OAuth authorization URL

* **Type:** `str`
* **Default:** `"https://auth.atlassian.com/authorize"`
* **Override:** `GENESIS__OAUTH_PROVIDERS__JIRA__AUTHORIZATION_URL`

#### `oauth_providers.jira.token_url`

Jira OAuth token URL

* **Type:** `str`
* **Default:** `"https://auth.atlassian.com/oauth/token"`
* **Override:** `GENESIS__OAUTH_PROVIDERS__JIRA__TOKEN_URL`

#### `oauth_providers.jira.scopes`

Jira OAuth scopes requested during user consent

* **Type:** `list`
* **Default:** `["read:jira-user", "offline_access"]`
* **Override:** `GENESIS__OAUTH_PROVIDERS__JIRA__SCOPES`

#### `oauth_providers.jira.guide_base_url`

Saved helper base URL for Jira OAuth setup guidance

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__JIRA__GUIDE_BASE_URL`

#### `oauth_providers.jira.guide_connection_name`

Saved helper connection name for Jira OAuth setup guidance

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__JIRA__GUIDE_CONNECTION_NAME`

### oauth\_providers.servicenow

#### `oauth_providers.servicenow.client_id`

ServiceNow OAuth client ID (set via Config UI, not env var)

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__SERVICENOW__CLIENT_ID`

#### `oauth_providers.servicenow.client_secret`

ServiceNow OAuth client secret reference/value

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__SERVICENOW__CLIENT_SECRET`
* **Secret**

#### `oauth_providers.servicenow.authorization_url`

ServiceNow OAuth authorization URL (supports \{host} template)

* **Type:** `str`
* **Default:** `"https://{host}/oauth_auth.do"`
* **Override:** `GENESIS__OAUTH_PROVIDERS__SERVICENOW__AUTHORIZATION_URL`

#### `oauth_providers.servicenow.token_url`

ServiceNow OAuth token URL (supports \{host} template)

* **Type:** `str`
* **Default:** `"https://{host}/oauth_token.do"`
* **Override:** `GENESIS__OAUTH_PROVIDERS__SERVICENOW__TOKEN_URL`

#### `oauth_providers.servicenow.scopes`

ServiceNow OAuth scopes requested during user consent

* **Type:** `list`
* **Default:** `["useraccount"]`
* **Override:** `GENESIS__OAUTH_PROVIDERS__SERVICENOW__SCOPES`

#### `oauth_providers.servicenow.guide_base_url`

Saved helper base URL for ServiceNow OAuth setup guidance

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__SERVICENOW__GUIDE_BASE_URL`

#### `oauth_providers.servicenow.guide_connection_name`

Saved helper connection name for ServiceNow OAuth setup guidance

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__SERVICENOW__GUIDE_CONNECTION_NAME`

### oauth\_providers.sharepoint

#### `oauth_providers.sharepoint.client_id`

SharePoint OAuth client ID (set via Config UI, not env var)

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__SHAREPOINT__CLIENT_ID`

#### `oauth_providers.sharepoint.client_secret`

SharePoint OAuth client secret reference/value

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__SHAREPOINT__CLIENT_SECRET`
* **Secret**

#### `oauth_providers.sharepoint.authorization_url`

SharePoint OAuth authorization URL (supports \{host} template)

* **Type:** `str`
* **Default:** `"https://login.microsoftonline.com/{host}/oauth2/v2.0/authorize"`
* **Override:** `GENESIS__OAUTH_PROVIDERS__SHAREPOINT__AUTHORIZATION_URL`

#### `oauth_providers.sharepoint.token_url`

SharePoint OAuth token URL (supports \{host} template)

* **Type:** `str`
* **Default:** `"https://login.microsoftonline.com/{host}/oauth2/v2.0/token"`
* **Override:** `GENESIS__OAUTH_PROVIDERS__SHAREPOINT__TOKEN_URL`

#### `oauth_providers.sharepoint.scopes`

SharePoint OAuth scopes requested during user consent

* **Type:** `list`
* **Default:** `["Sites.Read.All", "Files.Read.All", "offline_access"]`
* **Override:** `GENESIS__OAUTH_PROVIDERS__SHAREPOINT__SCOPES`

#### `oauth_providers.sharepoint.guide_base_url`

Saved helper base URL for SharePoint OAuth setup guidance

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__SHAREPOINT__GUIDE_BASE_URL`

#### `oauth_providers.sharepoint.guide_connection_name`

Saved helper connection name for SharePoint OAuth setup guidance

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__SHAREPOINT__GUIDE_CONNECTION_NAME`

### oauth\_providers.microsoft\_teams

#### `oauth_providers.microsoft_teams.client_id`

Microsoft Teams OAuth client ID (set via Config UI, not env var)

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__MICROSOFT_TEAMS__CLIENT_ID`

#### `oauth_providers.microsoft_teams.client_secret`

Microsoft Teams OAuth client secret reference/value

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__MICROSOFT_TEAMS__CLIENT_SECRET`
* **Secret**

#### `oauth_providers.microsoft_teams.authorization_url`

Microsoft Teams OAuth authorization URL (supports \{tenant\_id} template)

* **Type:** `str`
* **Default:** `"https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/authorize"`
* **Override:** `GENESIS__OAUTH_PROVIDERS__MICROSOFT_TEAMS__AUTHORIZATION_URL`

#### `oauth_providers.microsoft_teams.token_url`

Microsoft Teams OAuth token URL (supports \{tenant\_id} template)

* **Type:** `str`
* **Default:** `"https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token"`
* **Override:** `GENESIS__OAUTH_PROVIDERS__MICROSOFT_TEAMS__TOKEN_URL`

#### `oauth_providers.microsoft_teams.scopes`

Microsoft Teams OAuth scopes requested during user consent

* **Type:** `list`
* **Default:** shown below
* **Override:** `GENESIS__OAUTH_PROVIDERS__MICROSOFT_TEAMS__SCOPES`

```json theme={null}
[
  "ChannelMessage.Send",
  "ChatMessage.Send",
  "Chat.ReadWrite",
  "Team.ReadBasic.All",
  "Channel.ReadBasic.All",
  "User.Read.All",
  "Files.ReadWrite.All",
  "offline_access"
]
```

#### `oauth_providers.microsoft_teams.guide_base_url`

Saved helper base URL for Microsoft Teams OAuth setup guidance

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__MICROSOFT_TEAMS__GUIDE_BASE_URL`

#### `oauth_providers.microsoft_teams.guide_connection_name`

Saved helper connection name for Microsoft Teams OAuth setup guidance

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__MICROSOFT_TEAMS__GUIDE_CONNECTION_NAME`

### oauth\_providers.google\_workspace

#### `oauth_providers.google_workspace.client_id`

Google Workspace OAuth client ID (set via Config UI, not env var)

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__GOOGLE_WORKSPACE__CLIENT_ID`

#### `oauth_providers.google_workspace.client_secret`

Google Workspace OAuth client secret reference/value

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__GOOGLE_WORKSPACE__CLIENT_SECRET`
* **Secret**

#### `oauth_providers.google_workspace.authorization_url`

Google Workspace OAuth authorization URL

* **Type:** `str`
* **Default:** `"https://accounts.google.com/o/oauth2/v2/auth"`
* **Override:** `GENESIS__OAUTH_PROVIDERS__GOOGLE_WORKSPACE__AUTHORIZATION_URL`

#### `oauth_providers.google_workspace.token_url`

Google Workspace OAuth token URL

* **Type:** `str`
* **Default:** `"https://oauth2.googleapis.com/token"`
* **Override:** `GENESIS__OAUTH_PROVIDERS__GOOGLE_WORKSPACE__TOKEN_URL`

#### `oauth_providers.google_workspace.scopes`

Google Workspace OAuth scopes requested during user consent (read-only by default; write scopes added via incremental auth)

* **Type:** `list`
* **Default:** shown below
* **Override:** `GENESIS__OAUTH_PROVIDERS__GOOGLE_WORKSPACE__SCOPES`

```json theme={null}
[
  "https://www.googleapis.com/auth/drive.readonly",
  "https://www.googleapis.com/auth/spreadsheets.readonly",
  "https://www.googleapis.com/auth/presentations.readonly",
  "https://www.googleapis.com/auth/documents.readonly",
  "openid",
  "email"
]
```

#### `oauth_providers.google_workspace.guide_base_url`

Saved helper base URL for Google Workspace OAuth setup guidance

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__GOOGLE_WORKSPACE__GUIDE_BASE_URL`

#### `oauth_providers.google_workspace.guide_connection_name`

Saved helper connection name for Google Workspace OAuth setup guidance

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__OAUTH_PROVIDERS__GOOGLE_WORKSPACE__GUIDE_CONNECTION_NAME`

## Branding

#### `branding.organization_name`

Organization display name for branding

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__BRANDING__ORGANIZATION_NAME`

#### `branding.primary_color`

Primary brand color (hex code)

* **Type:** `str`
* **Default:** `"#F97316"`
* **Override:** `GENESIS__BRANDING__PRIMARY_COLOR`

#### `branding.secondary_color`

Secondary brand color (hex code)

* **Type:** `str`
* **Default:** `"#78350F"`
* **Override:** `GENESIS__BRANDING__SECONDARY_COLOR`

#### `branding.tertiary_color`

Tertiary brand color (hex code)

* **Type:** `str`
* **Default:** `"#1E3A5F"`
* **Override:** `GENESIS__BRANDING__TERTIARY_COLOR`

#### `branding.app_design_guidance`

Freeform app design guidance injected into app creation and editing prompts

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__BRANDING__APP_DESIGN_GUIDANCE`

#### `branding.use_logo_in_header`

Apply the uploaded organization logo to the main Genesis UI header. Off by default, so uploading a logo never changes the platform header until an admin opts in. Uploaded logos are always applied to Genesis-generated apps regardless of this setting.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__BRANDING__USE_LOGO_IN_HEADER`

## Database & Service Connections

#### `connection`

External service and database connections. Managed via Connections UI.

* **Type:** `dict`
* **Default:** `{}`
* **Override:** `GENESIS__CONNECTION`

## Connection Finder

#### `connection_finder.use_immutable_audit_for_search`

Write finder searches to the immutable audit store instead of structured logs

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__CONNECTION_FINDER__USE_IMMUTABLE_AUDIT_FOR_SEARCH`

## Mcp Servers

#### `mcp_servers`

Runtime HTTP MCP server registrations. Managed via Connections UI and the MCP admin tools.

* **Type:** `dict`
* **Default:** `{}`
* **Override:** `GENESIS__MCP_SERVERS`

## Servicenow

#### `servicenow.extra_tables`

Additional ServiceNow tables (beyond incident/change\_request/sc\_request/sc\_req\_item) the connector tool may read and write

* **Type:** `list`
* **Default:** `[]`
* **Override:** `GENESIS__SERVICENOW__EXTRA_TABLES`

## Outpost

#### `outpost.enabled`

Route connections to private hosts through customer-run Outposts. An Outpost runs in the customer's network, dials out to this Genesis over its tunnel endpoint, and carries the connections routed through it (outpost.outposts). Off: no hostname is mapped, no outpost\_ secret reference resolves, and the reconcile job stays paused.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__OUTPOST__ENABLED`

#### `outpost.outposts`

Outposts by name: \{name: \{slot: 1-250, serves: \[host patterns], route\_roles: \[role names], tunnel\_credentials: 'own', tunnel\_key\_id: \<16 hex digits>}}. tunnel\_credentials and tunnel\_key\_id are written by Genesis when an Outpost is created or issued a tunnel key (the key itself is a Genesis secret, never stored here). Every Outpost signs in to the tunnel server only with its own key; one without a tunnel\_key\_id cannot sign in until a key is issued on the Outposts page. The slot picks the loopback range 127.77.\<slot>.0/24 where the Outpost's destinations appear inside Genesis; two Outposts may not share a slot. A connection is routed through an Outpost when it chooses it (its locator's outpost field); serves optionally lists fnmatch patterns such as '\*.corp.internal' that route a whole domain without that choice. route\_roles lists the RBAC roles, besides admins, that may route connections through the Outpost. An invalid definition disables routing rather than guessing.

* **Type:** `dict`
* **Default:** `{}`
* **Override:** `GENESIS__OUTPOST__OUTPOSTS`

#### `outpost.reconcile_interval_seconds`

Safety-net interval for the Outpost route reconcile, which recomputes routed destinations from the connections, rewrites the managed hosts-file block, and tells each Outpost which tunnel listeners to hold. Routing is event-driven without it: a connection write that adds, moves or removes an Outpost-served host reconciles at once, Genesis reconciles once at startup, and an Outpost request that finds its Outpost unreachable re-sends that Outpost its routes; a restarted Outpost also restores its last routes from its own state file. This job only catches a change that bypassed those paths. 0 disables it.

* **Type:** `int`
* **Default:** `3600`
* **Minimum:** `0`
* **Override:** `GENESIS__OUTPOST__RECONCILE_INTERVAL_SECONDS`

#### `outpost.enforce_tunnel_admission`

Forward a connection to an Outpost route (a 127.77.\<slot>.\<n>:\<port> listener of Genesis's tunnel server) only when it comes from Genesis's own processes. On: running as root (Snowflake SPCS, Docker, Kubernetes) the tunnel server admits a connection only from a root-owned socket, so code in the cortex\_sandbox account is refused; running as one non-root account (a Databricks App) it also refuses a socket held by a process in another user namespace (the code sandbox), or by no process it can see. Each accepted connection costs one kernel netlink lookup, plus one /proc scan on a Databricks App; a refused connection is closed unread and logged once a minute per listener, account and reason. Off: every connection to a route listener is forwarded. A change restarts the tunnel server within about 15 seconds, which drops open tunnel connections.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__OUTPOST__ENFORCE_TUNNEL_ADMISSION`

#### `outpost.tunnel_endpoint_url`

Public URL of this Genesis's Outpost tunnel endpoint, shown in Outpost install instructions as the Outpost's GENESIS\_ENDPOINT. Unset: in Snowflake SPCS it is looked up from the service's outposttunnel endpoint (one SHOW ENDPOINTS query per install-instructions request); elsewhere it is the address the install wizard was opened at, followed by /outpost-tunnel (the App URL alone in a Databricks App, where the Outpost adds the path), and outside SPCS an agent asking without a browser gets a placeholder (in SPCS the endpoint lookup still applies). Set it when the lookup cannot see the endpoint or the Outpost must dial a different address.

* **Type:** `str`
* **Default:** `null`
* **Override:** `GENESIS__OUTPOST__TUNNEL_ENDPOINT_URL`

## Connectors

#### `connectors.engine_cache_max_entries`

Maximum SQLAlchemy engines retained by the process-wide DatabaseConnector cache. Entries are least-recently-used and include credential identity, so OAuth rotation and distinct personal credentials create separate engines. Eviction disposes the engine and clears all related cache state. Read when a new engine is published.

* **Type:** `int`
* **Default:** `64`
* **Minimum:** `1`
* **Override:** `GENESIS__CONNECTORS__ENGINE_CACHE_MAX_ENTRIES`
* **Environment default:** `GENESIS_ENGINE_CACHE_MAX_ENTRIES`

#### `connectors.engine_cache_max_entries_per_connection`

Maximum engines one connection may hold in the DatabaseConnector cache for one credential, counting its per-database and per-catalog variants together. A connection over the cap evicts and disposes that credential's least-recently-used engine, so one connection touching many databases or catalogs cannot evict other connections' engines; engines of other users on the same connection do not count. engine\_cache\_max\_entries still bounds the whole cache, and that bound evicts the least-recently-used engine of any connection. Read when a new engine is published.

* **Type:** `int`
* **Default:** `32`
* **Minimum:** `1`
* **Override:** `GENESIS__CONNECTORS__ENGINE_CACHE_MAX_ENTRIES_PER_CONNECTION`

#### `connectors.snowflake_spcs_internal_credentials_enabled`

Allow Snowflake PAT and key-pair connections flagged 'Connect inside Snowflake' (spcs\_internal) to log in over the SPCS-internal \$SNOWFLAKE\_HOST with their own credentials, so unattended work reaches the account Genesis runs in without egress (PrivateLink accounts). Off: saving a flagged connection is refused and a flagged connection refuses to connect; no other connection is affected. The install must also run CALL CORE.ENABLE\_CUSTOM\_CREDENTIALS() so its service spec carries enableCustomCredentials. Read at call time.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__CONNECTORS__SNOWFLAKE_SPCS_INTERNAL_CREDENTIALS_ENABLED`

#### `connectors.resolved_connection_cache_ttl_seconds`

TTL (seconds) for the process-wide resolved-connection cache on DatabaseConnector, which reuses one SUCCESSFUL connection resolution (secret decrypt + RBAC + connection-string build, and any Databricks OAuth mint) across the many queries a scan fires at a single connection. Two freshness guards bound staleness: the connection-catalog epoch drops an entry the instant a connection is created/updated/deleted, and this TTL bounds credential-ROTATION staleness (rotating a secret's value in place does NOT bump the epoch). Keep it well under any minted-token lifetime (Databricks service-principal OAuth \~1h) so a cached connection string never outlives its token. A value \<= 0 disables the cache entirely (always resolve fresh). Read at call time.

* **Type:** `float`
* **Default:** `60.0`
* **Override:** `GENESIS__CONNECTORS__RESOLVED_CONNECTION_CACHE_TTL_SECONDS`
* **Environment default:** `GENESIS_RESOLVED_CONNECTION_CACHE_TTL_SECONDS`

#### `connectors.duckdb_memory_limit_gb`

Per-connection DuckDB buffer-manager cap in GB, applied as SET memory\_limit on every DuckDB connection Genesis opens (duckdb:// user connections, the local Iceberg facade, PyIceberg query scratch DBs, iceberg-worker scratch DBs). DuckDB's own default is 80% of HOST RAM, which inside a memory-limited container exceeds the cgroup budget — the kernel then OOM-kills the whole backend before DuckDB's eviction/spill path engages. With a cap, an oversized query evicts and spills to DuckDB's temp directory or fails alone with a clean OutOfMemoryException. 0 disables the cap (DuckDB default applies). Read at connection time.

* **Type:** `float`
* **Default:** `2.0`
* **Minimum:** `0`
* **Override:** `GENESIS__CONNECTORS__DUCKDB_MEMORY_LIMIT_GB`
* **Environment default:** `GENESIS_DUCKDB_MEMORY_LIMIT_GB`

#### `connectors.connect_preflight_interval_seconds`

How long (seconds) a SUCCESSFUL pre-query connectivity preflight stays valid for one cached SQLAlchemy engine before the next query re-runs it. The preflight is an explicit connect + 'SELECT 1' under a hard timeout, and it costs a FULL EXTRA ROUND TRIP on every query — measured at \~28% of local wall-clock and one of four driver round trips per logical query, which is the dominant per-query tax on a large estate scan (an estatechar characterization issues \~21 queries per object, so a 540-object estate fires \~11k queries). Liveness is independently guaranteed: every engine is built with pool\_pre\_ping, and the query path already disposes-and-retries once (and drives the Snowflake token-expiry rebuild) on failure — so the preflight's unique value is FIRST contact with a freshly built engine, which always still runs. State is keyed by the engine-cache key (per-database for postgres), and is dropped whenever the engine is rebuilt, invalidated, or a query fails. A value \<= 0 restores the legacy preflight-every-query behavior. Read at call time.

* **Type:** `float`
* **Default:** `300.0`
* **Override:** `GENESIS__CONNECTORS__CONNECT_PREFLIGHT_INTERVAL_SECONDS`
* **Environment default:** `GENESIS_CONNECT_PREFLIGHT_INTERVAL_SECONDS`

#### `connectors.palantir_foundry_timeout_seconds`

Per-request socket timeout (seconds) for an INTERACTIVE Palantir Foundry client — the agent tools, where a person is waiting on the answer and a wedged request is worse than a refusal. Applies to every HTTP call the Foundry REST client makes on that path (resource walks, schema reads, and the legacy data-proxy SQL route, whose reads are Spark jobs rather than lookups). Read at call time; a scan uses connectors.palantir\_foundry\_scan\_timeout\_seconds instead. Before config is initialized (a direct, no-server run of the Prover as a library) the built-in 120s applies.

* **Type:** `int`
* **Default:** `120`
* **Minimum:** `1`
* **Override:** `GENESIS__CONNECTORS__PALANTIR_FOUNDRY_TIMEOUT_SECONDS`

#### `connectors.palantir_foundry_scan_timeout_seconds`

Per-request socket timeout (seconds) for a Palantir Foundry client built for a Prover SCAN or contract verification, where one statement legitimately runs for many minutes on the tenant's Spark and a timeout costs the whole run rather than one answer. MEASURED on the seeded Developer Tier tenant (2026-09-08): at 120s two whole-estate runs wedged in the per-column pass and stopped at 17 of 24 objects after >1,400s, while 900s completed 23 of 23 in-boundary objects in 1,510s — the identical SELECT COUNT(\*) on one dataset returned in 0.7s on one attempt and took 422s on another, so what this bounds is the tenant's compute, not the network. Raise it for a slower tenant; lowering it below the interactive value makes no sense. Read at call time.

* **Type:** `int`
* **Default:** `900`
* **Minimum:** `1`
* **Override:** `GENESIS__CONNECTORS__PALANTIR_FOUNDRY_SCAN_TIMEOUT_SECONDS`

#### `connectors.palantir_foundry_measurement_budget_seconds`

Elapsed budget (seconds) for one Foundry Prover characterization, starting before its scope and catalog walks. Remaining objects become named unread results after expiry; completed measurements are kept. The default 3600s comfortably exceeds the observed healthy 1510s run and is longer than the 2400s stale window, so the Foundry characterization heartbeat must remain active throughout the run. Other Foundry query users have no shared budget. Read at characterization start; direct no-server runs use the same built-in default.

* **Type:** `int`
* **Default:** `3600`
* **Minimum:** `1`
* **Override:** `GENESIS__CONNECTORS__PALANTIR_FOUNDRY_MEASUREMENT_BUDGET_SECONDS`

#### `connectors.palantir_foundry_sql_upstream_attempts`

How many times one Palantir Foundry SQL query is attempted while it fails transiently, before it fails with Foundry's own error. It caps two retries separately: the public /api/v2/sqlQueries/execute submission while Foundry's SQL service answers 5xx (its own service failing, not the query or the data; Foundry R13, 2026-09-28, errored 26 of 37 grade obligations on those 500s), and the whole query while it fails in transport (broken pipe, reset connection, read timeout) or the legacy data-proxy route answers 5xx (Foundry R16, 2026-09-30, lost two attempts at a 1.66M-row extract that way). The public route's 403 on a dataset's inputs is never itself retried, and a legacy-route 403 is a real permission denial that fails at once. 1 switches both retries off; a 4xx is never retried. Each attempt is a Spark job on the customer's tenant. Read at call time when a connection-backed client is built; before config is initialized the built-in 4 applies.

* **Type:** `int`
* **Default:** `4`
* **Minimum:** `1`
* **Maximum:** `10`
* **Override:** `GENESIS__CONNECTORS__PALANTIR_FOUNDRY_SQL_UPSTREAM_ATTEMPTS`

#### `connectors.palantir_foundry_sql_upstream_backoff_ceiling_seconds`

The longest single wait (seconds) between those Palantir Foundry SQL submission attempts. The waits double from 1 s (1, 2, 4, ...) and each is capped here, so one query waits at most (attempts - 1) x this value before it fails. The wait blocks only the worker thread running the query, never the event loop. Read at call time; before config is initialized the built-in 30 s applies.

* **Type:** `int`
* **Default:** `30`
* **Minimum:** `1`
* **Override:** `GENESIS__CONNECTORS__PALANTIR_FOUNDRY_SQL_UPSTREAM_BACKOFF_CEILING_SECONDS`

## Ticket Automation

#### `ticket_automation.auto_track_chat_requests`

Automatically create Requests for accepted Slack and Microsoft Teams messages. When disabled, chat conversations become Requests only when a user asks the agent to track or promote them. Slack threads and Teams channel reply chains reuse one Request; unquoted Teams personal/group-chat messages start separate Requests.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__TICKET_AUTOMATION__AUTO_TRACK_CHAT_REQUESTS`

### ticket\_automation.azure\_devops

#### `ticket_automation.azure_devops.enabled`

Enable polling Azure Boards for open work items assigned to the connection identity

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__TICKET_AUTOMATION__AZURE_DEVOPS__ENABLED`

#### `ticket_automation.azure_devops.poll_interval_seconds`

Cadence in seconds for polling Azure Boards assignments (minimum 30)

* **Type:** `int`
* **Default:** `60`
* **Override:** `GENESIS__TICKET_AUTOMATION__AZURE_DEVOPS__POLL_INTERVAL_SECONDS`

#### `ticket_automation.azure_devops.connection_name`

Azure DevOps connection used by assignment automation

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__TICKET_AUTOMATION__AZURE_DEVOPS__CONNECTION_NAME`

#### `ticket_automation.azure_devops.project`

Azure DevOps project whose assigned work items are polled

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__TICKET_AUTOMATION__AZURE_DEVOPS__PROJECT`

#### `ticket_automation.azure_devops.orchestrator_bot_id`

Genesis bot that handles each assigned Azure Boards work item

* **Type:** `str`
* **Default:** `"Eve"`
* **Override:** `GENESIS__TICKET_AUTOMATION__AZURE_DEVOPS__ORCHESTRATOR_BOT_ID`

#### `ticket_automation.azure_devops.run_as_user_id`

Internal owner identity used to preserve personal-connection access for background polling

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__TICKET_AUTOMATION__AZURE_DEVOPS__RUN_AS_USER_ID`

### ticket\_automation.linear

Software Factory — Development tooling. Do not change these settings unless configuring Linear-driven development automation.

#### `ticket_automation.linear.enabled`

Enable polling Linear for agent-ready coding tickets

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__TICKET_AUTOMATION__LINEAR__ENABLED`

#### `ticket_automation.linear.poll_interval_seconds`

Logical cadence in seconds for polling Linear (minimum 30)

* **Type:** `int`
* **Default:** `60`
* **Override:** `GENESIS__TICKET_AUTOMATION__LINEAR__POLL_INTERVAL_SECONDS`

#### `ticket_automation.linear.connection_name`

Linear connection name used by the automation system principal

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__TICKET_AUTOMATION__LINEAR__CONNECTION_NAME`

#### `ticket_automation.linear.agent_identity`

Linear delegate name or ID whose assigned issues are handled across all teams

* **Type:** `str`
* **Default:** `"Eve"`
* **Override:** `GENESIS__TICKET_AUTOMATION__LINEAR__AGENT_IDENTITY`

#### `ticket_automation.linear.working_state`

Linear workflow state applied when automation claims a ticket

* **Type:** `str`
* **Default:** `"Agent-Working"`
* **Override:** `GENESIS__TICKET_AUTOMATION__LINEAR__WORKING_STATE`

#### `ticket_automation.linear.review_state`

Linear workflow state applied after successful coding-agent review

* **Type:** `str`
* **Default:** `"HumanReview"`
* **Override:** `GENESIS__TICKET_AUTOMATION__LINEAR__REVIEW_STATE`

#### `ticket_automation.linear.needs_info_state`

Linear workflow state used when requirements or execution need input

* **Type:** `str`
* **Default:** `"Clarify"`
* **Override:** `GENESIS__TICKET_AUTOMATION__LINEAR__NEEDS_INFO_STATE`

#### `ticket_automation.linear.orchestrator_bot_id`

Genesis bot that orchestrates each claimed Linear ticket

* **Type:** `str`
* **Default:** `"Eve"`
* **Override:** `GENESIS__TICKET_AUTOMATION__LINEAR__ORCHESTRATOR_BOT_ID`

#### `ticket_automation.linear.run_as_user_id`

Persisted user who owns new Linear automation threads and supplies their tool permissions. Required for sandbox MCP access; empty preserves the legacy system owner.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__TICKET_AUTOMATION__LINEAR__RUN_AS_USER_ID`

### ticket\_automation.servicenow

#### `ticket_automation.servicenow.enabled`

Enable polling ServiceNow for records assigned or mentioned to Genesis

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__TICKET_AUTOMATION__SERVICENOW__ENABLED`

#### `ticket_automation.servicenow.ingestion_mode`

ServiceNow intake mode: polling, webhook, or hybrid

* **Type:** `str`
* **Default:** `"polling"`
* **Options:** `polling`, `webhook`, `hybrid`
* **Override:** `GENESIS__TICKET_AUTOMATION__SERVICENOW__INGESTION_MODE`

#### `ticket_automation.servicenow.poller_flow_id`

Managed ServiceNow polling Flow identifier

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__TICKET_AUTOMATION__SERVICENOW__POLLER_FLOW_ID`

#### `ticket_automation.servicenow.poller_job_id`

Managed ServiceNow polling Flow scheduler job identifier

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__TICKET_AUTOMATION__SERVICENOW__POLLER_JOB_ID`

#### `ticket_automation.servicenow.poller_schedule_status`

Managed ServiceNow polling Flow schedule status

* **Type:** `str`
* **Default:** `"not_configured"`
* **Override:** `GENESIS__TICKET_AUTOMATION__SERVICENOW__POLLER_SCHEDULE_STATUS`

#### `ticket_automation.servicenow.poll_interval_seconds`

Cadence in seconds for polling ServiceNow (minimum 30)

* **Type:** `int`
* **Default:** `60`
* **Override:** `GENESIS__TICKET_AUTOMATION__SERVICENOW__POLL_INTERVAL_SECONDS`

#### `ticket_automation.servicenow.poll_lookback_minutes`

How far back the first/recovery polling pass looks for updated records

* **Type:** `int`
* **Default:** `15`
* **Override:** `GENESIS__TICKET_AUTOMATION__SERVICENOW__POLL_LOOKBACK_MINUTES`

#### `ticket_automation.servicenow.poll_max_results`

Maximum updated records examined per table per polling pass

* **Type:** `int`
* **Default:** `50`
* **Override:** `GENESIS__TICKET_AUTOMATION__SERVICENOW__POLL_MAX_RESULTS`

#### `ticket_automation.servicenow.connection_name`

ServiceNow connection name used by the automation service identity

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__TICKET_AUTOMATION__SERVICENOW__CONNECTION_NAME`

#### `ticket_automation.servicenow.bot_id`

Genesis bot that picks up triggered ServiceNow records

* **Type:** `str`
* **Default:** `"Eve"`
* **Override:** `GENESIS__TICKET_AUTOMATION__SERVICENOW__BOT_ID`

#### `ticket_automation.servicenow.tables`

ServiceNow tables the automation polls (must be on the tool allowlist)

* **Type:** `list`
* **Default:** `["incident"]`
* **Override:** `GENESIS__TICKET_AUTOMATION__SERVICENOW__TABLES`

#### `ticket_automation.servicenow.record_query`

Optional extra encoded-query filter ANDed into every polling query

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__TICKET_AUTOMATION__SERVICENOW__RECORD_QUERY`

#### `ticket_automation.servicenow.trigger_type`

Trigger mode: assignment, status, status\_or\_assignment, comment\_keyword, or hybrid

* **Type:** `str`
* **Default:** `"hybrid"`
* **Override:** `GENESIS__TICKET_AUTOMATION__SERVICENOW__TRIGGER_TYPE`

#### `ticket_automation.servicenow.assigned_to`

Tracked assignee for the Genesis service user (sys\_user user\_name, sys\_id, or display name)

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__TICKET_AUTOMATION__SERVICENOW__ASSIGNED_TO`

#### `ticket_automation.servicenow.trigger_on_states`

State values or labels that trigger pickup when a record enters them

* **Type:** `list`
* **Default:** `[]`
* **Override:** `GENESIS__TICKET_AUTOMATION__SERVICENOW__TRIGGER_ON_STATES`

#### `ticket_automation.servicenow.trigger_on_comment_keywords`

Keywords/mentions in new comments or work notes that trigger pickup

* **Type:** `list`
* **Default:** `["@genesis", "genesis"]`
* **Override:** `GENESIS__TICKET_AUTOMATION__SERVICENOW__TRIGGER_ON_COMMENT_KEYWORDS`

#### `ticket_automation.servicenow.state_on_pickup`

Optional state value/label applied when Genesis picks up a record

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__TICKET_AUTOMATION__SERVICENOW__STATE_ON_PICKUP`

#### `ticket_automation.servicenow.state_on_needs_info`

Optional state suggested to the agent when requirements are incomplete

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__TICKET_AUTOMATION__SERVICENOW__STATE_ON_NEEDS_INFO`

#### `ticket_automation.servicenow.state_on_done`

Optional state suggested to the agent when work is finished

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__TICKET_AUTOMATION__SERVICENOW__STATE_ON_DONE`

#### `ticket_automation.servicenow.writeback_journal_field`

Journal field for automation write-backs: work\_notes (internal) or comments (customer-visible)

* **Type:** `str`
* **Default:** `"work_notes"`
* **Override:** `GENESIS__TICKET_AUTOMATION__SERVICENOW__WRITEBACK_JOURNAL_FIELD`

#### `ticket_automation.servicenow.webhook_secret`

Shared HMAC secret for the inbound ServiceNow webhook route (empty disables webhook intake)

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__TICKET_AUTOMATION__SERVICENOW__WEBHOOK_SECRET`
* **Secret**

## Genesis Enhancements — Software Factory / Development tooling

Optional development automation; not required for standard production deployments. Do not change these settings unless explicitly configuring Software Factory.

### genesis\_enhancements.cursor\_agent

#### `genesis_enhancements.cursor_agent.enabled`

Enable the coding-agent launcher (local runner or Cursor Cloud)

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CURSOR_AGENT__ENABLED`
* **Environment default:** `CURSOR_AGENT_TICKET_ENABLED`

#### `genesis_enhancements.cursor_agent.adapter`

auto | local | cloud. auto: local if a runner command is configured, else cloud if a connection is configured. Explicit cloud overrides a configured local runner.

* **Type:** `str`
* **Default:** `"auto"`
* **Options:** `auto`, `local`, `cloud`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CURSOR_AGENT__ADAPTER`

#### `genesis_enhancements.cursor_agent.connection_name`

Name of the shared-scope cursor connection used by the cloud adapter

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CURSOR_AGENT__CONNECTION_NAME`

#### `genesis_enhancements.cursor_agent.target_repo_url`

GitHub repository URL cloud agents work on

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CURSOR_AGENT__TARGET_REPO_URL`

#### `genesis_enhancements.cursor_agent.target_base_ref`

Base ref cloud agents start from

* **Type:** `str`
* **Default:** `"main"`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CURSOR_AGENT__TARGET_BASE_REF`
* **Environment default:** `CURSOR_AGENT_TARGET_BRANCH`

#### `genesis_enhancements.cursor_agent.auto_create_pr`

Ask Cursor Cloud to open a PR automatically on completion

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CURSOR_AGENT__AUTO_CREATE_PR`

#### `genesis_enhancements.cursor_agent.model`

Optional Cursor Cloud model slug to pin for new runs; empty string inherits the Cursor workspace default

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CURSOR_AGENT__MODEL`

### genesis\_enhancements.coding\_agent

### genesis\_enhancements.coding\_agent.review

#### `genesis_enhancements.coding_agent.review.enabled`

Enable server-managed PR review and correction for Claude Code and GitHub Actions Factory runs. Cursor retains its existing Eve-owned settlement and does not enroll in this review loop.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__REVIEW__ENABLED`

#### `genesis_enhancements.coding_agent.review.max_rounds`

Maximum coding correction runs per active review cycle. Zero means unlimited; polling and retries do not consume rounds.

* **Type:** `int`
* **Default:** `0`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__REVIEW__MAX_ROUNDS`

#### `genesis_enhancements.coding_agent.review.active_cycle_timeout_seconds`

Active review correction budget in seconds. Idle monitoring for later feedback has no deadline. Active coding children retain their own runtime deadline.

* **Type:** `int`
* **Default:** `28800`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__REVIEW__ACTIVE_CYCLE_TIMEOUT_SECONDS`

#### `genesis_enhancements.coding_agent.backend`

Which coding backend runs coding tasks. Changing it takes effect on the next dispatch without a restart; runs already in flight keep refreshing through the backend that started them.

* **Type:** `str`
* **Default:** `"sandbox_claude"`
* **Options:** `cursor`, `claude_code`, `github_actions`, `sandbox_claude`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__BACKEND`

### genesis\_enhancements.coding\_agent.claude\_code

#### `genesis_enhancements.coding_agent.claude_code.enabled`

Enable the Claude coding backend. Read instead of the cursor\_agent flag when backend=claude\_code.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__CLAUDE_CODE__ENABLED`

#### `genesis_enhancements.coding_agent.claude_code.connection_name`

Name of the claude\_code connection holding the coding credential. Production runs use a LiteLLM virtual key, which is what carries the per-flow budget and the authoritative spend record; the subscription OAuth profile is a development convenience.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__CLAUDE_CODE__CONNECTION_NAME`

#### `genesis_enhancements.coding_agent.claude_code.git_connection_name`

Name of the github connection whose GitHub App identity pushes the branch and opens the PR. Separate from connection\_name, which is the model credential.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__CLAUDE_CODE__GIT_CONNECTION_NAME`

#### `genesis_enhancements.coding_agent.claude_code.target_repo_url`

GitHub repository URL the backend clones and works in

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__CLAUDE_CODE__TARGET_REPO_URL`

#### `genesis_enhancements.coding_agent.claude_code.target_base_ref`

Base ref every run's worktree is cut from

* **Type:** `str`
* **Default:** `"main"`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__CLAUDE_CODE__TARGET_BASE_REF`

#### `genesis_enhancements.coding_agent.claude_code.model`

Optional model slug to pin for new runs; empty string inherits the Claude CLI default

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__CLAUDE_CODE__MODEL`

#### `genesis_enhancements.coding_agent.claude_code.worktree_root`

Directory holding the base clone and per-run worktrees. On EKS this is the container writable layer and does not survive a pod restart; run evidence is persisted separately under the run root.

* **Type:** `str`
* **Default:** `"/opt/genesis-agents-start-cursor-agent"`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__CLAUDE_CODE__WORKTREE_ROOT`

#### `genesis_enhancements.coding_agent.claude_code.max_concurrent_runs`

How many tickets the Linear poller may hold claimed at once. Each run costs a worktree plus a full test suite on the pod that also serves the product API.

* **Type:** `int`
* **Default:** `1`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__CLAUDE_CODE__MAX_CONCURRENT_RUNS`

#### `genesis_enhancements.coding_agent.claude_code.max_verify_cycles`

How many times a run may re-run its own verification gates after a failure before stopping. Stopping is not a pass: the ticket parks.

* **Type:** `int`
* **Default:** `3`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__CLAUDE_CODE__MAX_VERIFY_CYCLES`

#### `genesis_enhancements.coding_agent.claude_code.verify_timeout_seconds`

Wall-clock limit on one verification subprocess

* **Type:** `int`
* **Default:** `2700`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__CLAUDE_CODE__VERIFY_TIMEOUT_SECONDS`

#### `genesis_enhancements.coding_agent.claude_code.run_deadline_seconds`

Wall-clock limit on the whole run. Nothing else reaps the runner process in a pod.

* **Type:** `int`
* **Default:** `7200`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__CLAUDE_CODE__RUN_DEADLINE_SECONDS`

### genesis\_enhancements.coding\_agent.sandbox\_claude

#### `genesis_enhancements.coding_agent.sandbox_claude.enabled`

Enable the Sandbox Runner coding backend.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__SANDBOX_CLAUDE__ENABLED`

#### `genesis_enhancements.coding_agent.sandbox_claude.runtime`

Optional transport override. Blank inherits sandbox\_runner.runtime.

* **Type:** `str`
* **Default:** `""`
* **Options:** \`\`, `docker`, `kubernetes`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__SANDBOX_CLAUDE__RUNTIME`

#### `genesis_enhancements.coding_agent.sandbox_claude.image`

Trusted toolchain image. Preload it for Docker; use an immutable tag in deployments.

* **Type:** `str`
* **Default:** `"genesis-sandbox-claude-coding:latest"`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__SANDBOX_CLAUDE__IMAGE`

#### `genesis_enhancements.coding_agent.sandbox_claude.namespace`

Dedicated Kubernetes coding namespace, separate from chat sandboxes.

* **Type:** `str`
* **Default:** `"genesis-coding"`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__SANDBOX_CLAUDE__NAMESPACE`

#### `genesis_enhancements.coding_agent.sandbox_claude.storage_class`

Optional storage class override. Blank inherits sandbox\_runner.k8s\_storage\_class.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__SANDBOX_CLAUDE__STORAGE_CLASS`

#### `genesis_enhancements.coding_agent.sandbox_claude.storage_size`

Retained per-session workspace and Claude home PVC capacity.

* **Type:** `str`
* **Default:** `"20Gi"`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__SANDBOX_CLAUDE__STORAGE_SIZE`

#### `genesis_enhancements.coding_agent.sandbox_claude.network`

Optional Docker network override. Blank inherits sandbox\_runner.network.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__SANDBOX_CLAUDE__NETWORK`

#### `genesis_enhancements.coding_agent.sandbox_claude.cpu_request`

Kubernetes CPU request per coding worker.

* **Type:** `str`
* **Default:** `"1"`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__SANDBOX_CLAUDE__CPU_REQUEST`

#### `genesis_enhancements.coding_agent.sandbox_claude.cpu_limit`

CPU limit per coding worker.

* **Type:** `str`
* **Default:** `"4"`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__SANDBOX_CLAUDE__CPU_LIMIT`

#### `genesis_enhancements.coding_agent.sandbox_claude.memory_request`

Kubernetes memory request per coding worker.

* **Type:** `str`
* **Default:** `"2Gi"`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__SANDBOX_CLAUDE__MEMORY_REQUEST`

#### `genesis_enhancements.coding_agent.sandbox_claude.memory_limit`

Memory limit per coding worker.

* **Type:** `str`
* **Default:** `"8Gi"`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__SANDBOX_CLAUDE__MEMORY_LIMIT`

#### `genesis_enhancements.coding_agent.sandbox_claude.service_account`

Kubernetes worker service account. API token mounting is disabled.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__SANDBOX_CLAUDE__SERVICE_ACCOUNT`

#### `genesis_enhancements.coding_agent.sandbox_claude.runtime_class`

Optional RuntimeClass override. Blank inherits sandbox\_runner.k8s\_runtime\_class.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__SANDBOX_CLAUDE__RUNTIME_CLASS`

#### `genesis_enhancements.coding_agent.sandbox_claude.image_pull_secrets`

Kubernetes image pull secret names in the dedicated coding namespace.

* **Type:** `list`
* **Default:** `[]`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__SANDBOX_CLAUDE__IMAGE_PULL_SECRETS`

#### `genesis_enhancements.coding_agent.sandbox_claude.git_connection_name`

Parent-only GitHub connection used to seed objects and publish verified commits.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__SANDBOX_CLAUDE__GIT_CONNECTION_NAME`

#### `genesis_enhancements.coding_agent.sandbox_claude.target_repo_url`

Trusted GitHub HTTPS repository URL; never passed as an authenticated remote to the worker.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__SANDBOX_CLAUDE__TARGET_REPO_URL`

#### `genesis_enhancements.coding_agent.sandbox_claude.target_base_ref`

Base ref for a first coding run.

* **Type:** `str`
* **Default:** `"main"`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__SANDBOX_CLAUDE__TARGET_BASE_REF`

#### `genesis_enhancements.coding_agent.sandbox_claude.model`

Optional Claude model label; the Genesis proxy resolves the thread model.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__SANDBOX_CLAUDE__MODEL`

#### `genesis_enhancements.coding_agent.sandbox_claude.max_concurrent_runs`

Fixed at 1: one accepted coding run, including preparation and publication. Other values disable this backend.

* **Type:** `int`
* **Default:** `1`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__SANDBOX_CLAUDE__MAX_CONCURRENT_RUNS`

#### `genesis_enhancements.coding_agent.sandbox_claude.max_verify_cycles`

Maximum agent verification attempts; exhaustion fails the run.

* **Type:** `int`
* **Default:** `3`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__SANDBOX_CLAUDE__MAX_VERIFY_CYCLES`

#### `genesis_enhancements.coding_agent.sandbox_claude.verify_timeout_seconds`

Wall-clock limit for one unchanged repository verification command.

* **Type:** `int`
* **Default:** `2700`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__SANDBOX_CLAUDE__VERIFY_TIMEOUT_SECONDS`

#### `genesis_enhancements.coding_agent.sandbox_claude.run_deadline_seconds`

Bootstrap and coding deadline; must fit the existing scoped credential lifetime.

* **Type:** `int`
* **Default:** `7200`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__SANDBOX_CLAUDE__RUN_DEADLINE_SECONDS`

#### `genesis_enhancements.coding_agent.sandbox_claude.startup_timeout_seconds`

Deadline for source transfer and resource preparation.

* **Type:** `int`
* **Default:** `900`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__SANDBOX_CLAUDE__STARTUP_TIMEOUT_SECONDS`

#### `genesis_enhancements.coding_agent.sandbox_claude.transfer_timeout_seconds`

Timeout for one bounded Git or sandbox file transfer.

* **Type:** `int`
* **Default:** `300`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__SANDBOX_CLAUDE__TRANSFER_TIMEOUT_SECONDS`

#### `genesis_enhancements.coding_agent.sandbox_claude.transfer_limit_bytes`

Maximum bytes per source or result Git bundle.

* **Type:** `int`
* **Default:** `2147483648`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__SANDBOX_CLAUDE__TRANSFER_LIMIT_BYTES`

#### `genesis_enhancements.coding_agent.sandbox_claude.session_retention_seconds`

Retain workspace and Claude home for follow-up after a terminal run. A run that ended without collected evidence or with failed publication keeps its workspace for this long after it finished, then it is released.

* **Type:** `int`
* **Default:** `86400`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__SANDBOX_CLAUDE__SESSION_RETENTION_SECONDS`

#### `genesis_enhancements.coding_agent.sandbox_claude.proxy_base_url`

Optional proxy URL override. Blank inherits sandbox\_runner.proxy\_base\_url and its runtime-derived default.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__SANDBOX_CLAUDE__PROXY_BASE_URL`

#### `genesis_enhancements.coding_agent.sandbox_claude.mcp_url`

Optional MCP URL override. Blank inherits sandbox\_runner.mcp\_url and its runtime-derived default.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__SANDBOX_CLAUDE__MCP_URL`

### genesis\_enhancements.coding\_agent.github\_actions

#### `genesis_enhancements.coding_agent.github_actions.enabled`

Enable the GitHub Actions coding backend. Read instead of the cursor\_agent flag when backend=github\_actions.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__GITHUB_ACTIONS__ENABLED`

#### `genesis_enhancements.coding_agent.github_actions.github_connection_name`

Name of the github connection whose GitHub App identity dispatches the workflow, reads its run and artifacts, and reads the pull request's CI. The model credential is not here: it is a GitHub secret the workflow reads, because the runner is where it is spent.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__GITHUB_ACTIONS__GITHUB_CONNECTION_NAME`

#### `genesis_enhancements.coding_agent.github_actions.target_repo_url`

GitHub repository URL the workflow runs in

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__GITHUB_ACTIONS__TARGET_REPO_URL`

#### `genesis_enhancements.coding_agent.github_actions.target_base_ref`

Base ref a first attempt starts from; a retry starts from the branch its predecessor published

* **Type:** `str`
* **Default:** `"main"`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__GITHUB_ACTIONS__TARGET_BASE_REF`

#### `genesis_enhancements.coding_agent.github_actions.workflow_file`

File name of the dispatched workflow, as the Actions API names it

* **Type:** `str`
* **Default:** `"autodev-coding-run.yml"`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__GITHUB_ACTIONS__WORKFLOW_FILE`

#### `genesis_enhancements.coding_agent.github_actions.workflow_ref`

Ref the workflow file is taken from. GitHub only exposes a workflow\_dispatch workflow whose file exists on the default branch, so a branch named here must also exist on it.

* **Type:** `str`
* **Default:** `"main"`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__GITHUB_ACTIONS__WORKFLOW_REF`

#### `genesis_enhancements.coding_agent.github_actions.model`

Model or proxy model group to pin for new runs. An empty value is a refusal, not a default: the CLI would substitute a vendor model the proxy's model group does not serve.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__GITHUB_ACTIONS__MODEL`

#### `genesis_enhancements.coding_agent.github_actions.max_concurrent_runs`

How many tickets the Linear poller may hold claimed at once. Each run costs a GitHub-hosted runner rather than capacity on the pod that serves the product API.

* **Type:** `int`
* **Default:** `1`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__GITHUB_ACTIONS__MAX_CONCURRENT_RUNS`

#### `genesis_enhancements.coding_agent.github_actions.max_verify_cycles`

How many times a run may re-run its own verification gates after a failure before stopping. Stopping is not a pass: the ticket parks.

* **Type:** `int`
* **Default:** `3`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__GITHUB_ACTIONS__MAX_VERIFY_CYCLES`

#### `genesis_enhancements.coding_agent.github_actions.verify_timeout_seconds`

Wall-clock limit on one verification subprocess

* **Type:** `int`
* **Default:** `2700`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__GITHUB_ACTIONS__VERIFY_TIMEOUT_SECONDS`

#### `genesis_enhancements.coding_agent.github_actions.run_deadline_seconds`

Wall-clock limit on the whole run, enforced by the run itself. The workflow's job timeout is the backstop for a runner that cannot.

* **Type:** `int`
* **Default:** `7200`
* **Override:** `GENESIS__GENESIS_ENHANCEMENTS__CODING_AGENT__GITHUB_ACTIONS__RUN_DEADLINE_SECONDS`

## System Diff

#### `system_diff.concurrency_limit`

Max concurrent verification queries permitted PER EVENT LOOP (the query semaphore permit count). Genesis runs a single Uvicorn loop, so in practice this is a process-wide cap. Kept well below the 20-thread shared executor to leave headroom for the rest of the server.

* **Type:** `int`
* **Default:** `8`
* **Override:** `GENESIS__SYSTEM_DIFF__CONCURRENCY_LIMIT`

#### `system_diff.query_budget`

Total number of database queries a single verification run may issue before it stops early and reports truncated=true (verdict INDETERMINATE unless a mismatch was already confirmed). Bounds the bisect/tolerance fan-out on large tables.

* **Type:** `int`
* **Default:** `10000`
* **Override:** `GENESIS__SYSTEM_DIFF__QUERY_BUDGET`

#### `system_diff.query_timeout_minutes`

Per-query timeout (minutes) passed to DatabaseConnector.query\_database for every verification query. Raise for large tables/warehouses where a single checksum or tolerance page legitimately takes longer than 2 minutes.

* **Type:** `float`
* **Default:** `2.0`
* **Override:** `GENESIS__SYSTEM_DIFF__QUERY_TIMEOUT_MINUTES`

#### `system_diff.tolerance_page_size`

Row page size for the method-3 keyed tolerance value-diff stream. Larger pages mean fewer round-trips but more rows pulled per query.

* **Type:** `int`
* **Default:** `5000`
* **Override:** `GENESIS__SYSTEM_DIFF__TOLERANCE_PAGE_SIZE`

#### `system_diff.max_mismatched_keys`

In-memory cap on the mismatched keys a run collects. Keys beyond the cap are counted into mismatched\_keys\_overflow (and mark the run truncated) rather than stored, so wide drift at scale cannot blow out memory.

* **Type:** `int`
* **Default:** `10000`
* **Override:** `GENESIS__SYSTEM_DIFF__MAX_MISMATCHED_KEYS`

### system\_diff.reconcile

#### `system_diff.reconcile.enabled`

Master switch for the scheduler-driven open-deviation reconcile loop (consumed by revision C / GEN-2162). Default off: no background re-checks until an operator opts in.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__SYSTEM_DIFF__RECONCILE__ENABLED`

#### `system_diff.reconcile.interval_seconds`

Seconds between reconcile passes when system\_diff.reconcile.enabled is true. Also feeds the escalation age math (revision C).

* **Type:** `int`
* **Default:** `300`
* **Override:** `GENESIS__SYSTEM_DIFF__RECONCILE__INTERVAL_SECONDS`

#### `system_diff.reconcile.resolve_after`

Number of consecutive passing reconcile passes after which an open deviation is aged out as resolved/timing-noise.

* **Type:** `int`
* **Default:** `3`
* **Override:** `GENESIS__SYSTEM_DIFF__RECONCILE__RESOLVE_AFTER`

#### `system_diff.reconcile.escalate_after`

Number of reconcile passes (or lag windows) a deviation must persist before it is escalated to real-regression.

* **Type:** `int`
* **Default:** `3`
* **Override:** `GENESIS__SYSTEM_DIFF__RECONCILE__ESCALATE_AFTER`

### system\_diff.retention

#### `system_diff.retention.enabled`

Master switch for the scheduler-driven retention/compaction pass (GEN-2164). Default off: the reconciliation store never deletes anything until an operator opts in.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__SYSTEM_DIFF__RETENTION__ENABLED`

#### `system_diff.retention.interval_seconds`

Seconds between retention/compaction passes when system\_diff.retention.enabled is true. Compaction is bounded per pass, so a leftover backlog is drained by subsequent passes rather than one long sweep. Set \<= 0 to skip registering the job entirely.

* **Type:** `int`
* **Default:** `86400`
* **Override:** `GENESIS__SYSTEM_DIFF__RETENTION__INTERVAL_SECONDS`

#### `system_diff.retention.terminal_diff_days`

Delete terminal-status open diffs (timing-noise, known-tolerance) whose last\_seen is older than this many days. Only terminal statuses are ever eligible: real-regression and hot-suspended represent open work and are never auto-deleted. Set \<= 0 to disable terminal-diff deletion while leaving run-history pruning active.

* **Type:** `int`
* **Default:** `30`
* **Override:** `GENESIS__SYSTEM_DIFF__RETENTION__TERMINAL_DIFF_DAYS`

#### `system_diff.retention.run_history_keep`

Number of most-recent verification runs to keep per spec\_name; older runs and their object\_results rows are deleted. Set \<= 0 to disable run-history pruning while leaving terminal-diff deletion active.

* **Type:** `int`
* **Default:** `50`
* **Override:** `GENESIS__SYSTEM_DIFF__RETENTION__RUN_HISTORY_KEEP`

#### `system_diff.retention.batch_limit`

Maximum rows a single retention pass deletes per category (terminal diffs, pruned runs, diff events). Bounds the work one scheduler tick can do so compaction never turns into a full-table sweep; the remainder is picked up by the next pass.

* **Type:** `int`
* **Default:** `1000`
* **Override:** `GENESIS__SYSTEM_DIFF__RETENTION__BATCH_LIMIT`

#### `system_diff.retention.event_days`

Delete at-transition diff evidence records (comparison\_diff\_events) older than this many days. Deliberately longer than terminal\_diff\_days: the trail exists to outlive the state row it describes, so a resolution followed by a reopen can still be reconstructed after the deviation itself has been compacted away. These are durable evidence records, explicitly not a tamper-evident hash chain. Set \<= 0 to keep diff events forever.

* **Type:** `int`
* **Default:** `90`
* **Override:** `GENESIS__SYSTEM_DIFF__RETENTION__EVENT_DAYS`

## Action Review

#### `action_review.standing_grants_enabled`

Administrator's switch for standing permissions. On: a person approving an Action Review card for an action they asked an agent for may also choose "Approve and allow similar", which lets that agent take similar actions for that person without a card (in every chat, or only that chat), within the narrow scope the card states (for a bash command: changing files in one project folder, with no internet and no sign-ins). Destructive, credential-revealing and admin-level actions always ask. Off: no permission is offered, saved or honoured, and an action already proposed under one does not run. Checked live, on every action; no restart is needed.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ACTION_REVIEW__STANDING_GRANTS_ENABLED`

#### `action_review.sweep_interval_seconds`

Seconds between Action Review cleanup sweeps. Expiry is enforced in decision and claim predicates; this sweep only materializes expired rows and reconciles stale claims.

* **Type:** `int`
* **Default:** `600`
* **Override:** `GENESIS__ACTION_REVIEW__SWEEP_INTERVAL_SECONDS`

#### `action_review.claim_stale_after_seconds`

Age in seconds after which a claimed Action Review proposal moves to reconciliation\_required. This must exceed all provider execution timeouts so an in-flight action is not swept.

* **Type:** `int`
* **Default:** `900`
* **Override:** `GENESIS__ACTION_REVIEW__CLAIM_STALE_AFTER_SECONDS`

#### `action_review.store_large_text_by_reference`

Store each long text in a new Action Review proposal once, in a side table, instead of repeating it in every payload column; the proposal's intent always keeps its own inline copy. A file edit otherwise repeats the file's text about twenty times in one proposal row, and on Snowflake a row over the 1 MB statement limit is refused. Off (default): proposals are written inline, exactly as earlier builds wrote them. Rows stored by reference are read correctly whether this is on or off. ROLLBACK WARNING: once this is on and a large proposal has been written, rolling back to a build older than the one that introduced this setting can invalidate pending approvals, because the older build cannot read the stored form and treats the approval as changed. Turn it on only on a release you will not roll back past.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__ACTION_REVIEW__STORE_LARGE_TEXT_BY_REFERENCE`

#### `action_review.snowflake_hybrid_tables`

On a Snowflake metadata database, create the Action Review ledger's per-approval tables (proposals, their sealed events and their text blobs) as Snowflake hybrid tables, which answer keyed reads and writes about a third faster than standard tables (measured on env3: the ledger's statements in one package approval took 6.2 s instead of 9.3 s). Read when the ledger is first used after a start. It creates missing tables only: an existing standard table is never converted while Genesis runs, because the server and its worker processes may be writing; it is named in a warning, and the operator converts it with Genesis stopped by running scripts/convert\_action\_review\_ledger\_to\_hybrid.py --genesis-is-stopped, which keeps each original as \<table>*standard*\<timestamp>. Hybrid tables are created without CHECK constraints, which Snowflake cannot alter on them; the store writes their status, admission outcome and authorization basis only from its own constants. Where the account cannot create hybrid tables, they are created standard and the failure is logged. Off (default): standard tables, as before. Turning it off later does not convert back.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__ACTION_REVIEW__SNOWFLAKE_HYBRID_TABLES`

## Salesforce

#### `salesforce.max_approval_ttl_seconds`

Maximum lifetime in seconds callers may request for a Salesforce merge approval before it expires.

* **Type:** `int`
* **Default:** `86400`
* **Override:** `GENESIS__SALESFORCE__MAX_APPROVAL_TTL_SECONDS`

#### `salesforce.merge_claim_stale_after_seconds`

Age in seconds after which recovery marks an abandoned Salesforce merge claim failed with an unknown remote outcome. This must exceed the default merge execution timeout of 60 seconds so an in-flight merge is not swept.

* **Type:** `int`
* **Default:** `900`
* **Override:** `GENESIS__SALESFORCE__MERGE_CLAIM_STALE_AFTER_SECONDS`

## HubSpot

#### `hubspot.max_approval_ttl_seconds`

Maximum lifetime in seconds callers may request for a HubSpot merge approval before it expires.

* **Type:** `int`
* **Default:** `86400`
* **Override:** `GENESIS__HUBSPOT__MAX_APPROVAL_TTL_SECONDS`

#### `hubspot.merge_claim_stale_after_seconds`

Age in seconds after which recovery marks an abandoned HubSpot merge claim failed with an unknown remote outcome. This must exceed the default merge execution timeout of 60 seconds so an in-flight merge is not swept.

* **Type:** `int`
* **Default:** `900`
* **Override:** `GENESIS__HUBSPOT__MERGE_CLAIM_STALE_AFTER_SECONDS`

#### `hubspot.extra_objects`

Additional HubSpot CRM object types an administrator permits the connector to read and mutate.

* **Type:** `list`
* **Default:** `[]`
* **Override:** `GENESIS__HUBSPOT__EXTRA_OBJECTS`

## Transition Contract

#### `transition_contract.ratifier_public_keys`

Named Ed25519 public keys, encoded as base64 raw-32 values, authorized to ratify correspondence-rule bindings.

* **Type:** `dict`
* **Default:** `{}`
* **Override:** `GENESIS__TRANSITION_CONTRACT__RATIFIER_PUBLIC_KEYS`

#### `transition_contract.ratifier_private_key`

Base64-encoded raw-32 Ed25519 private key resolved for each in-app approval and used to sign transition bindings. Its public half must be listed in ratifier\_public\_keys.

* **Type:** `str`
* **Override:** `GENESIS__TRANSITION_CONTRACT__RATIFIER_PRIVATE_KEY`
* **Startup environment variable:** `RATIFIER_PRIVATE_KEY`
* **Secret**

#### `transition_contract.ratifier_key_id`

Name (key id) under ratifier\_public\_keys whose private half is ratifier\_private\_key; stamped into signed bindings as public\_key\_id.

* **Type:** `str`
* **Default:** `"local"`
* **Override:** `GENESIS__TRANSITION_CONTRACT__RATIFIER_KEY_ID`

## Org Health

#### `org_health.fix_mode`

Controls whether the GenesisAuditor may propose organization fixes. 'silent' (default) refuses every fix proposal and every Apply; 'active' lets the identity-bound auditor propose fixes to organization content re-proved under the current policy and corpus, each of which waits in Action Review until a person who may manage the target applies it. Unset, unreadable, and unrecognized values fail closed to 'silent'. Vocabulary matches estate\_char.adjudicator.mode deliberately: env-override casting turns the strings 'on'/'off' into booleans before the schema sees them, so those values can never arrive via GENESIS\_\_ overrides.

* **Type:** `str`
* **Default:** `"silent"`
* **Options:** `silent`, `active`
* **Override:** `GENESIS__ORG_HEALTH__FIX_MODE`

#### `org_health.proposal_payload_max_bytes`

Conservative pre-admission ceiling in bytes for the handler-known serialized proposal-row content of organization fixes that edit a whole blueprint manifest or skill document. The ceiling leaves headroom for policy admission, attested origin, SQL encoding, and other row metadata that are added after the handler's check. Oversized fixes are refused before Action Review stores a proposal. Uninitialized, unset, unparseable, nonpositive, and unreadable runtime values use the 750000-byte default.

* **Type:** `int`
* **Default:** `750000`
* **Minimum:** `1`
* **Override:** `GENESIS__ORG_HEALTH__PROPOSAL_PAYLOAD_MAX_BYTES`

## Estate Char

#### `estate_char.allow_unverified_sealing`

Interim setting for a deployment running with sign-in off (auth.enabled false) while its identity provider is set up, off by default. When true, sealing a source contract and deciding a mined candidate are no longer refused on that stack: a request made from the page is recorded as 'local operator (auth disabled)', or, when the request names someone in its X-Genesis-Signed-As header, as that name followed by '(self-reported, auth disabled)', so every such seal says it was not verified. An agent's own tool call and a delegated or app-only token are still refused. Has no effect once sign-in is on. Note that with sign-in off anyone who can reach the server can change this setting, so turn it on only where network access is already restricted, and off once sign-in is live. A seal made this way is not replaced when sign-in is turned on.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__ESTATE_CHAR__ALLOW_UNVERIFIED_SEALING`

### estate\_char.api

#### `estate_char.api.max_wait_seconds`

Ceiling (seconds) on the OPTIONAL internal wait a caller may ask a run-creating route for with `wait_seconds`. Everything the Prover does is asynchronous and returns a run handle at once (ruling F.3); a caller that would rather block than poll names a wait, and this bounds it. A request above the ceiling is clamped, not refused, and the clamp is disclosed on the response (`wait.requested_seconds` beside `wait.ceiling_seconds`) so a caller can tell the operator's bound from its own. When the wait expires the route answers 202 with the same handle and the WORK CONTINUES — the ceiling bounds how long a request holds a connection, never how long a run may take. Bounded 1..3600s: below 1s no wait could ever succeed, and above an hour a request would outlive every proxy in front of it. Read at call time.

* **Type:** `int`
* **Default:** `300`
* **Minimum:** `1`
* **Maximum:** `3600`
* **Override:** `GENESIS__ESTATE_CHAR__API__MAX_WAIT_SECONDS`

### estate\_char.mechanical\_baseline

#### `estate_char.mechanical_baseline.enabled`

Master switch for the GEN-2594 mechanical baseline (always-on invariants + materiality-gated ambiguity choice-detectors) in the conformance grader. Default OFF: the grade is byte-identical to the pre-baseline behavior until an operator opts in after the calibration harness measures \~0 actionable false positives on the verifier-green controls. When true, only the families listed in estate\_char.mechanical\_baseline.families run; the mechanical output rides its own report block and never enters the numbered-issue surface.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__ESTATE_CHAR__MECHANICAL_BASELINE__ENABLED`

#### `estate_char.mechanical_baseline.families`

The calibration-gated set of check families permitted to run when enabled. A family ships in this list only after the harness measures its false-positive rate on the controls as acceptable. 1a invariants (near-zero FP by construction): inf\_nan (non-finite numeric metric), null\_grain\_keys (a NULL in a declared grain key), conservation\_declared (a declared FK with orphan rows), cumulative\_monotonic (designed, engine-hook pending — abstains). 1b choice-detectors (materiality-gated): orphan\_population (include-vs-exclude orphans), weighted\_aggregate + percentile\_direction (designed, engine-hook pending — abstain). The default omits every choice-detector, so flipping enabled on fires only the three near-zero-FP invariants. An unknown id is ignored (forward-safe).

* **Type:** `list`
* **Default:** `["inf_nan", "null_grain_keys", "conservation_declared"]`
* **Override:** `GENESIS__ESTATE_CHAR__MECHANICAL_BASELINE__FAMILIES`

#### `estate_char.mechanical_baseline.orphan_materiality_min_rows`

Minimum diverging orphan rows before the orphan\_population choice-detector treats the include-vs-exclude readings as materially different. At the default 1, any nonzero orphan population whose choice the spec left open is disclosed; raise it to suppress trivially-small populations. The materiality floor is the max of this and orphan\_materiality\_min\_fraction \* row\_count.

* **Type:** `int`
* **Default:** `1`
* **Override:** `GENESIS__ESTATE_CHAR__MECHANICAL_BASELINE__ORPHAN_MATERIALITY_MIN_ROWS`

#### `estate_char.mechanical_baseline.orphan_materiality_min_fraction`

Alternative materiality floor for orphan\_population as a fraction of the child object's row\_count; the larger of the two floors (this and orphan\_materiality\_min\_rows) wins. 0.0 (default) disables the fractional floor.

* **Type:** `float`
* **Default:** `0.0`
* **Override:** `GENESIS__ESTATE_CHAR__MECHANICAL_BASELINE__ORPHAN_MATERIALITY_MIN_FRACTION`

### estate\_char.spec\_author

#### `estate_char.spec_author.compile_timeout_seconds`

Per-call BUDGET (seconds) for ONE author call made by the reading consult — the single knob from which both timeout bounds derive. It IS the HTTP read timeout passed to the author's LLM call; the asyncio wall-clock ceiling that actually bounds the call is this budget plus a fixed 60s grace (see spec\_author\_runtime.author\_call\_bounds), so the HTTP timeout always fires first and a hung provider can never leak an orphaned to\_thread call — at ANY value set here. A consult asks one bounded question over sealed prose, so 900s is generous; on timeout the attempt is abandoned and, once chunk\_retry\_bound is exhausted, the consult run is stamped a terminal error, never left running. Total cost is bounded by this budget times (1 + chunk\_retry\_bound). The estatechar-core default is the same 900s. Bounded 30..3600s so an operator cannot set a value that either starves a real consult or lets a stuck agent hold a worker for an hour+. Read at call time.

* **Type:** `int`
* **Default:** `900`
* **Minimum:** `30`
* **Maximum:** `3600`
* **Override:** `GENESIS__ESTATE_CHAR__SPEC_AUTHOR__COMPILE_TIMEOUT_SECONDS`

#### `estate_char.spec_author.chunk_retry_bound`

How many EXTRA attempts the reading consult's author call gets after its first when it exits transiently. 0 means one attempt with no retry. Bounds cost: a consult runs at most (1 + this) author calls. The estatechar-core default is 2. Bounded 0..5 so retries cannot blow up total cost unboundedly. Read at call time.

* **Type:** `int`
* **Default:** `2`
* **Minimum:** `0`
* **Maximum:** `5`
* **Override:** `GENESIS__ESTATE_CHAR__SPEC_AUTHOR__CHUNK_RETRY_BOUND`

#### `estate_char.spec_author.author_concurrency`

Maximum concurrent reading-consult author calls per process. Each holds one to\_thread worker from the shared 50-thread budget at a time, so this caps the consult's draw on that budget — mandatory because an unbounded burst of submits could otherwise starve the event-loop executor. Clamped to >= 1 at call time. A process-wide asyncio semaphore wraps the author call; the estatechar-glue default is 2. Bounded 1..4 to protect the shared 50-thread budget. Read at call time.

* **Type:** `int`
* **Default:** `2`
* **Minimum:** `1`
* **Maximum:** `4`
* **Override:** `GENESIS__ESTATE_CHAR__SPEC_AUTHOR__AUTHOR_CONCURRENCY`

#### `estate_char.spec_author.escalation_mode`

How the spec-author seat treats an open question it cannot settle by measuring the estate. 'human' (default): the question is reported for a person and may hold the compile — the product, where humans exist and are useful. 'autonomous': no human court exists by design (benchmarks); the seat forks the reading, annotates the artifact, and continues, never blocking on a person. Read at call time via estatechar/genesis\_integration/spec\_author\_seat.py (the only reader) and consumed by the seat API when it composes the seat's brief and records the run; an unset or unrecognized value reads as 'human'.

* **Type:** `str`
* **Default:** `"human"`
* **Options:** `autonomous`, `human`
* **Override:** `GENESIS__ESTATE_CHAR__SPEC_AUTHOR__ESCALATION_MODE`

#### `estate_char.spec_author.interpretation_policy`

How the spec-author seat reads a ticket that leaves a choice open. 'lean', the only policy: commit to the most likely reading, fork with a lean, and flag the assumption. 'open' is retired: a configured 'open' is logged and read as 'lean', a run that names 'open' is refused, and a spec sealed under 'open' stays readable and is repaired under 'lean' (the repair run records the change in seat\_settings\_inherited). Recorded on the run's provenance and summary and on the seal's provenance. Read at call time via estatechar/genesis\_integration/spec\_author\_seat.py (the only reader); an unset or unrecognized value reads as 'lean'.

* **Type:** `str`
* **Default:** `"lean"`
* **Options:** `lean`
* **Override:** `GENESIS__ESTATE_CHAR__SPEC_AUTHOR__INTERPRETATION_POLICY`

#### `estate_char.spec_author.authoring_tooling`

Which tool set the spec-author seat authors with, for a NEW seat run whose commissioning call names none. 'registrar' (default): the Registrar's authoring tooling — progressive phases (scope\_population, model\_fields, obligations, final\_review) checkpointed on the run row, grounded bulk model-field registration (every derived target of the registered target model in one call), and field-level correction of a rejected obligation; a phase closes inside the registration that completes it (register\_model\_fields closes scope\_population and, once every declared derived column has its item, model\_fields), never in a model turn of its own; a fresh registrar round seals from any phase once every phase check passes on its draft, and the seal's record and the sealed run carry every phase's checkpoint; model\_fields is skipped when the registered target model declares no derived target and every changed object already has its structural item; the run's thread keeps its tool groups through the seal's closing turn and the Registrar group is withdrawn when the run ends (a Registrar verb called after the seal refuses and withdraws it at once); and a repair round skips the phases. 'classic' (the original tools, with no phases and no Registrar group) is retired for new specs and is not accepted here: a value of 'classic' is logged and read as 'registrar'. It remains only to repair a spec sealed with it — a repair round inherits it from its prior, or names it per run (authoring\_tooling='classic' with repair\_of naming the classic seal; a classic submit without one is refused before anything starts) — and a classic round that loads no prior spec is refused at the seal. A caller may override it for one run (author\_spec / POST author-seat 'authoring\_tooling'). Fixed when the run is created and recorded on the run's provenance and summary and on the seal's provenance, so changing this value affects only runs created afterwards; a repair round seeded from a prior seal must run with that seal's tooling (a seal recorded before this setting existed reads as 'classic'). Read at call time via estatechar/genesis\_integration/spec\_author\_seat.py (the only reader); an unset or unrecognized value reads as 'registrar'.

* **Type:** `str`
* **Default:** `"registrar"`
* **Options:** `registrar`
* **Override:** `GENESIS__ESTATE_CHAR__SPEC_AUTHOR__AUTHORING_TOOLING`

#### `estate_char.spec_author.poll_seconds`

How often (seconds) the spec-author SEAT driver re-reads its thread while the seat's turn is still running. On the async-dispatcher path the message send returns the instant the prompt is accepted, so the send is not the end of the turn: the driver polls at this cadence, keeping the run row's heartbeat alive, until the run's owner (reconcile\_seat\_run) reports a terminal status. Each poll is one thread-messages read plus, once a RESULT appears, one compiled-spec read — so a shorter cadence buys a faster terminal poll at the cost of more reads per turn; it does NOT affect the heartbeat cadence, which is derived from estate\_char.reconcile.stale\_after\_seconds. Bounded 1..300s so the driver can neither hammer the thread store nor let a finished turn sit unreported for minutes. Read at call time.

* **Type:** `int`
* **Default:** `20`
* **Minimum:** `1`
* **Maximum:** `300`
* **Override:** `GENESIS__ESTATE_CHAR__SPEC_AUTHOR__POLL_SECONDS`

#### `estate_char.spec_author.provider_fault_retry_seconds`

How long (seconds) the spec-author seat driver waits, quietly, before the FIRST automatic retry of a commission whose turn died on a provider fault — the model provider dropping or stalling its stream mid-turn (a Bedrock socket timeout, a mid-stream fallback). A seat commission is tens of minutes of authoring, and these faults are transient, so the run is not failed on the first one: after this wait the driver asks the seat to resume in the same thread, where its brief and every item it already registered survive. A retry sent while the provider is still out fails again, so each later retry waits twice as long as the one before (60s, 120s, 240s at the defaults), up to estate\_char.spec\_author.provider\_fault\_retry\_attempts retries and within estate\_char.spec\_author.provider\_fault\_retry\_ceiling\_seconds of total wait; a provider fault after the last retry ends the run 'failed' with error\_type provider\_fault. Faults that are not the provider's (an invalid or rejected request) are never retried, since re-sending them would fail the same way. The run's heartbeat is kept alive through every wait. 0 retries at once. Bounded 0..900s so the wait can neither outlive the stale-run window nor hammer a provider that just failed. Read at call time.

* **Type:** `int`
* **Default:** `60`
* **Minimum:** `0`
* **Maximum:** `900`
* **Override:** `GENESIS__ESTATE_CHAR__SPEC_AUTHOR__PROVIDER_FAULT_RETRY_SECONDS`

#### `estate_char.spec_author.provider_fault_retry_attempts`

How many automatic retries a spec-author seat commission gets after its turn dies on a provider fault, each after a cool-down twice as long as the one before it (starting at estate\_char.spec\_author.provider\_fault\_retry\_seconds). Measured basis: a Bedrock outage of about 7 minutes (F1 walk 9, 2026-09-28) outlasted the run's single retry at 60s, and the re-commissioned run cost about 30 minutes; three retries at 60s, 120s and 240s span 7 minutes of outage. A provider fault after the last retry ends the run 'failed' with error\_type provider\_fault. Bounded 1..6: at least the one retry a commission has always had, and few enough that a provider that is down for good fails the run within the ceiling. Read at call time.

* **Type:** `int`
* **Default:** `3`
* **Minimum:** `1`
* **Maximum:** `6`
* **Override:** `GENESIS__ESTATE_CHAR__SPEC_AUTHOR__PROVIDER_FAULT_RETRY_ATTEMPTS`

#### `estate_char.spec_author.provider_fault_retry_ceiling_seconds`

Ceiling (seconds) on the total quiet wait a spec-author seat commission spends across its provider-fault retries. The first retry is always taken after estate\_char.spec\_author.provider\_fault\_retry\_seconds; a later one only while the waits so far plus its own stay within this ceiling, so a provider that is down for good fails the run in bounded time. The seat's own turn time is not counted: each resumed turn has its own estate\_char.spec\_author.max\_turn\_seconds. Bounded 0..3600s; 0 allows only the first retry. Read at call time.

* **Type:** `int`
* **Default:** `900`
* **Minimum:** `0`
* **Maximum:** `3600`
* **Override:** `GENESIS__ESTATE_CHAR__SPEC_AUTHOR__PROVIDER_FAULT_RETRY_CEILING_SECONDS`

#### `estate_char.spec_author.max_registration_calls`

Ceiling on how many REGISTRATION calls (register\_scope / register\_structural(s) / register\_obligation(s) / register\_settlement / register\_substrate) one spec-author seat thread may make before the tools refuse. The seat is a single bot turn that nothing can interrupt from outside — the driver's max\_turn\_seconds bounds only the DRIVER's wait — so this is the one place a runaway authoring turn is actually bounded, and the refusal is what ends it: past the ceiling every registration returns a refusal carrying what has been sealed so far by kind, the elapsed calls, and the literal next call to make (finalize\_spec with what is registered). Measured basis: a 26-table lift-and-shift spiralled to 172 register\_obligation calls over 33 minutes under the pre-v9.1 floors; under the SCOPE floor the same spec registers in single digits, so 200 is far above any legitimate run and far below a spiral. Counted per CALL, not per item — the bulk verbs exist so that many items cost one call, and a budget counting items would penalise exactly the behaviour it wants. Bounded 10..5000 so an operator can neither starve a genuinely large spec nor make the ceiling meaningless. Read at call time by genesis\_bots/core/tools/spec\_author\_tools.py.

* **Type:** `int`
* **Default:** `200`
* **Minimum:** `10`
* **Maximum:** `5000`
* **Override:** `GENESIS__ESTATE_CHAR__SPEC_AUTHOR__MAX_REGISTRATION_CALLS`

#### `estate_char.spec_author.max_turn_seconds`

Ceiling (seconds) on how long the spec-author seat DRIVER waits on one turn — not on the turn itself. Past it the driver stops stamping the run's heartbeat, writes a non-terminal note on the run summary saying the ceiling was reached and the turn may still complete, and lets go; it never stamps a terminal status. It cannot: on the no-adapter path the turn runs on a worker thread that cancelling an await can neither stop nor join, so a detached turn may still register a seal, and closing the row would leave that seal with nowhere to be adopted. Ownership passes to the two mechanisms already in place — the run stays derivable from its thread, so a RESULT that lands later is adopted on the next poll, and if none ever does the stale-run reconcile reaps the row as 'error' one estate\_char.reconcile.stale\_after\_seconds window after the note. This bounds the driver, which is what would otherwise heartbeat a wedged provider stream forever. Default 4h is well past the longest observed authoring turn. Bounded 60..86400s so the ceiling cannot be set below a real turn or so high that a wedged driver is effectively unbounded. Read at call time.

* **Type:** `int`
* **Default:** `14400`
* **Minimum:** `60`
* **Maximum:** `86400`
* **Override:** `GENESIS__ESTATE_CHAR__SPEC_AUTHOR__MAX_TURN_SECONDS`

#### `estate_char.spec_author.no_progress_seconds`

How long (seconds) a spec-author seat may go with NO progress before its driver ends the run. Progress is anything the seat's own thread counters record (a message or any accepted write) or a chunk its completion delivers in this process (a completion streaming in another process is not visible here, so there only the thread's writes are compared, and the run's error says so); the run row's heartbeat is the driver's and never counts. Past the bound the run ends terminal as error\_type run\_stalled, with a next act that says to start it again — instead of reading 'working' until max\_turn\_seconds (4h by default) and then the stale-run window. The stalled turn is not interrupted, so anything it writes later arrives as a late completion beside the row. A poll whose thread counters cannot be read gives no verdict either way, so an unreadable thread is never called stalled. Each poll reads the thread's named props once, a cache hit on the messages read the same poll already made. Default 30 min: twice the provider's own active-stream idle guard (llm.active\_stream\_idle\_timeout\_seconds, 900s) and three times the longest silence measured on a healthy seat (602s between chunks). Bounded 900..14400s: the floor is the provider's own idle guard, which is above the 602s healthy silence, so the bound can never cut a healthy completion short; the ceiling is the turn ceiling's default. The same bound ends a running Adjudicator proceeding whose seat has stopped making progress while its instance still reads live — the periodic estatechar reconcile compares the seat thread's counters across its passes (so the verdict lands within one estate\_char.reconcile.interval\_seconds of the bound) and fails the proceeding with the model provider's classified cause when the provider is not answering (an expired login, say), or the measured stall when it is. Read at call time.

* **Type:** `int`
* **Default:** `1800`
* **Minimum:** `900`
* **Maximum:** `14400`
* **Override:** `GENESIS__ESTATE_CHAR__SPEC_AUTHOR__NO_PROGRESS_SECONDS`

#### `estate_char.spec_author.stall_stop_attempts`

How many times a stall owner asks the runtime to stop a stalled turn before it gives up. When a spec-author seat run or an Adjudicator proceeding is found making no progress (estate\_char.spec\_author.no\_progress\_seconds), its owner asks the runtime's hard-stop to stop the turn BEFORE it writes the row terminal, because the terminal row is what a caller resubmits on. A refused request is asked again, estate\_char.spec\_author.stall\_stop\_retry\_seconds apart, up to this many requests in all; the row is retired when a request is taken, or when every one was refused — and then the row says the retries ran out, so a caller knows the old turn may still be running; this process then keeps asking it to stop (on every reconcile sweep, and whenever a replacement is submitted) and refuses a replacement in its scope — a seat run on the same connection for the same operator, a proceeding over the same comparison — until the runtime accepts a stop request or the turn leaves the runtime. The seat's driver holds the run (heartbeat still stamped) through the retries; the Adjudicator's reconcile sweep defers the proceeding and asks again on a later pass. Default 3. Bounded 1..10: one is a single ask with no retry; more than ten holds a stalled row for the better part of an hour at the longest interval. Read at call time.

* **Type:** `int`
* **Default:** `3`
* **Minimum:** `1`
* **Maximum:** `10`
* **Override:** `GENESIS__ESTATE_CHAR__SPEC_AUTHOR__STALL_STOP_ATTEMPTS`

#### `estate_char.spec_author.stall_stop_retry_seconds`

Seconds between a stall owner's requests to stop a stalled turn that the runtime refused (see estate\_char.spec\_author.stall\_stop\_attempts). The seat's driver waits this long on the event loop without blocking it (an asyncio sleep, no thread) while keeping the run's heartbeat; the Adjudicator's reconcile sweep does not ask again on a pass that comes sooner, so there the effective interval is at least one estate\_char.reconcile.interval\_seconds. Default 60. Bounded 5..600: faster than a turn reaches its next step asks for nothing new; slower holds a stalled row longer than the stop is worth. Read at call time.

* **Type:** `int`
* **Default:** `60`
* **Minimum:** `5`
* **Maximum:** `600`
* **Override:** `GENESIS__ESTATE_CHAR__SPEC_AUTHOR__STALL_STOP_RETRY_SECONDS`

### estate\_char.characterization

#### `estate_char.characterization.excluded_schemas`

Case-insensitive glob patterns for source schemas to EXCLUDE from full-source characterization. Every other discovered schema is scanned. Default excludes the Prover's own throwaway eval/stimulus sandbox clones (\*\_eval, \*\_stim) — not part of the real source estate. Any exclusion is recorded on the boundary (boundary.excluded\_schemas) and surfaced in the diff scope reconciliation, so it is never a silent habit. Set to \[] to scan literally every schema.

* **Type:** `list`
* **Default:** `["*_eval", "*_stim"]`
* **Override:** `GENESIS__ESTATE_CHAR__CHARACTERIZATION__EXCLUDED_SCHEMAS`

#### `estate_char.characterization.full_source_default`

When true (default), a characterize call that does NOT pin an explicit schema list scans the entire source estate (all schemas minus excluded\_schemas). Set false only to force callers to always name schemas explicitly (legacy pinned-subset behavior) — not recommended: subset scans cannot flag defects hiding in schemas the scan never touched.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__CHARACTERIZATION__FULL_SOURCE_DEFAULT`

#### `estate_char.characterization.timestamp_digest_precision`

Declared sub-second fidelity (fractional-second digits: 0, 3, or 6) of the timestamp content-digest recipe. This is the tolerance below which two instants fold equal. Microsecond (6, the default and the finest the dialect adapters render) so an instant tamper down to 1µs changes the fold — M11 D13 (+1µs on stg\_orders.order\_ts) evaded silently because the recipe truncated to milliseconds by accident. Recorded on the ObservationBoundary (boundary.timestamp\_digest\_precision) so it is an explicit, reviewable Π tolerance and both sides of a diff use the same precision. Set 3 (millisecond) or 0 (second) only to declare a deliberately coarser tolerance.

* **Type:** `int`
* **Default:** `6`
* **Override:** `GENESIS__ESTATE_CHAR__CHARACTERIZATION__TIMESTAMP_DIGEST_PRECISION`

#### `estate_char.characterization.reuse_connection`

When true (default), a Databricks estate characterization reuses ONE Databricks SQL connection across all of a scan's queries instead of opening a fresh connection per query. A full-estate scan fires \~90 queries per object (one single-scan aggregate, one top-K per column, up to 16 digest-frame scans), and the per-query TLS+Thrift-session handshake (\~0.5s) measured \~40% of scan wall-clock — reuse pays that handshake once instead of per-query. Reconnect-on-failure keeps a long scan resilient to a dropped/expired session (Databricks service-principal OAuth token \~1h). Databricks-ONLY: every other engine (incl. Snowflake, which owns its own token-expiry connection-rebuild dance) always uses the per-query connection path regardless of this flag. Set false to force the legacy per-query connect-query-close behavior on Databricks too.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__CHARACTERIZATION__REUSE_CONNECTION`

#### `estate_char.characterization.frozen_estate`

When true, declare the ENTIRE source estate a quiesced FROZEN snapshot: every object's temporal regime is 'frozen', so its content obligations are compiled as-is (stamped with the observation instant) and a cross-snapshot content mismatch is treated as a real defect — never excused as observation skew. This is the discipline a migration cutover wants (source held still while it is scanned). Default false: objects are classified per-object instead (append\_only where a monotone anchor is detected, else the conservative 'mutable'). Frozen is DECLARED, never inferred — set it only when you know the source was genuinely quiesced for the scan, because it turns off the skew-tolerance that keeps a live estate's legitimate row churn from reading as drift.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__ESTATE_CHAR__CHARACTERIZATION__FROZEN_ESTATE`

#### `estate_char.characterization.append_only_detection`

When true (default), an object with a NOT-NULL, near-unique (distinct-count ≈ row-count), monotone-typed creation/serial anchor column (created\_at / create\_date / inserted\_at / \*\_id / a declared watermark — never a mutation stamp like updated\_at / write\_date) is classified 'append\_only', so its content obligations compile as BOUNDED aggregates (WHERE anchor \<= T) that stay comparable as the tail grows. Set false to disable the heuristic and force every non-frozen non-wall-clock object to the conservative 'mutable' regime (its content mismatches under observation skew become indeterminate rather than bounded) — choose this when single-snapshot anchor detection would over-optimistically tag a mutable master table append\_only in your estate.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__CHARACTERIZATION__APPEND_ONLY_DETECTION`

#### `estate_char.characterization.resume_enabled`

When true (default), a characterize run stages each object's measurement the instant it is taken and, on relaunch under the IDENTICAL boundary + observation instant + measurement-library version, reuses the objects an interrupted run already measured and re-measures only the tail, then seals the combined snapshot. Provably safe: an ObjectMeasurement carries no wall-clock metadata in its content hash, the relaunch reuses the interrupted run's ORIGINAL observation instant (so append\_only WHERE anchor \<= T bounds and the sealed watermark match), and reuse is scoped by a lineage key over (boundary\_hash, observed\_at, measurement\_library\_version) — a different boundary, instant, or library version simply cannot see the staged rows, so epochs are never mixed. A lineage is cleared once its snapshot seals — unless the scan's measurement time limit ran out, in which case the lineage is kept so the next scan of the same scope within the window reuses the measured objects and measures only the rest. Set false to disable staging and resume entirely (every scan measures every object from scratch and a kill costs the whole scan).

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__CHARACTERIZATION__RESUME_ENABLED`

#### `estate_char.characterization.resume_window_seconds`

How recent an interrupted scan's staged progress must be, in seconds, for a relaunch to resume from it rather than start fresh — measured from the lineage's observation instant (every reused measurement is pinned to it) as well as its last write, so a chain of reruns cannot carry one instant past the window. Lineages past it are deleted by the periodic reconcile sweep. Resume is a prompt continuation of a killed scan, not a revival of an ancient one: beyond this window the source data may have drifted, so reusing the earlier half while re-measuring the tail could mix two epochs — the relaunch scans fresh instead. Default 86400 (24h). Set 0 (or negative) to refuse resume outright (staging still happens, but no lineage is ever reused); raise it only if you knowingly resume long-parked scans against a quiesced source.

* **Type:** `int`
* **Default:** `86400`
* **Override:** `GENESIS__ESTATE_CHAR__CHARACTERIZATION__RESUME_WINDOW_SECONDS`

#### `estate_char.characterization.carry_forward_enabled`

When true (default), a rescan of a boundary takes each table's measurement from that boundary's previous snapshot, byte for byte, when the engine's own table version proves the table unchanged (a Delta version from DESCRIBE HISTORY, which moves on every commit), and measures only the rest — so a reload of one table costs one table's measurement, not the whole estate's. A table is measured again when its version moved or cannot be read, its columns, nullability, declared keys or temporal-regime settings changed, a table its foreign keys point at was measured again, the caller named it, or the previous snapshot was taken under another boundary, measurement library or database principal. Only Databricks carries in this build: an Iceberg snapshot id misses metadata-only schema changes and rollbacks, and the other engines report no table version. The sealed snapshot names every carried object and the snapshot it came from (carried\_forward). Set false to measure every object on every scan.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__CHARACTERIZATION__CARRY_FORWARD_ENABLED`

### estate\_char.comparison

#### `estate_char.comparison.skew_warn_seconds`

Observation-skew threshold, in seconds, above which a system diff's summary carries a skew\_warning. Two estate snapshots are almost never observed at the same wall-clock instant; a large skew means any wall-clock-derived object (a VIEW keyed on current\_date, a rolling report window) will legitimately differ across the two reads. The mediated diff always records source\_observed\_at / target\_observed\_at / skew\_seconds; when skew\_seconds exceeds this threshold the summary adds a plain-language skew\_warning so a reviewer reads a time-dependent divergence as expected, not as a migration defect. Findings on objects tagged wall\_clock\_dependent are ruled indeterminate (time-dependent) whenever skew\_seconds > 0 regardless of this threshold — this knob only governs the summary-level warning. Default 3600 (1 hour). Set higher to suppress the banner for routine same-day scans, lower to surface even small skews.

* **Type:** `int`
* **Default:** `3600`
* **Override:** `GENESIS__ESTATE_CHAR__COMPARISON__SKEW_WARN_SECONDS`

#### `estate_char.comparison.case_insensitive_object_names`

When true, the mediated diff compares catalog identifiers case-insensitively across source and target objects and, within each paired object, its columns and declared-key members. A case-only object difference becomes a licensed object\_relocated instead of object\_missing + object\_surplus, while case-only column and key differences match in place. This addresses engines that fold unquoted identifiers on create — Snowflake upper-cases them and Spark/Databricks lower-cases them, so pairs such as MSSQL->Snowflake or Postgres->Databricks may need this policy. Guarded against silent data loss: multiple content-bearing object spellings or multiple column spellings that collapse to one identity are REFUSED and surfaced as addressing\_incoherence — case alone never merges distinct data. Default false means this policy contributes no case folding, so catalog correspondence stays exact-match unless a binding addressing rule independently supplies an explicit fold. This release also makes collisions under such binding column-fold rules fail closed even while this option is false; rerunning an affected comparison can therefore change findings, match counts, and its hash. Resolve the colliding physical names or revoke the binding rule before rerunning if that authority is no longer valid. This is the INSTANCE-WIDE DEFAULT; a single comparison can override it per request (POST /api/estate/system-diffs case\_insensitive\_object\_names, or the run\_system\_diff tool's parameter of the same name), because whether a case fold is legitimate is a property of the engine pair. Existing callers that already set true will now stop receiving case-only column and declared-key findings as well as object findings. To retain the earlier object-only result, set this false, supply explicit object correspondence through object\_map or reviewed addressing rules, and rerun the comparison; stored prior diffs are unchanged. Every comparison builds in-memory identity and collision indexes for each paired object's measured columns and keys, adding O(n log n) worst-case CPU and O(n) transient memory in those catalog entries but no database or file I/O. This policy and binding folds change the indexes' semantics, not whether they are built. Set this true only when MOST comparisons on the instance are cross-engine pairs whose target folds identifier case; otherwise leave it false and opt in per comparison.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__ESTATE_CHAR__COMPARISON__CASE_INSENSITIVE_OBJECT_NAMES`

#### `estate_char.comparison.auto_envelope`

When true (default), after a system diff registers a comparison for an estate pair, auto-materialize the migration-envelope spec-conformance run (ISS31 'there is always a spec'): a platform-clause-only sealed spec (source\_engine → target\_engine, zero change items) graded against the just-computed diff via the standard production-grading path. This is what lets EVERY comparison replay the full five-beat flow — the envelope opening, the blind-first comparison, and the on-stage Π (platform-rule) sort — instead of rendering a pre-sorted diff. The envelope asks nothing of the migration, so its grade reads 'No specification attached yet' rather than 'Not verified', it opens no findings and no Human Review worklist (there is nothing to review against until a spec is attached), and it is never the grade a comparison's card or chapter opens once any grade carrying a spec exists for that comparison. Idempotent (never a second run for the same diff\_hash), skips a diff a drill/eval already owns, skips the comparison a prove call with a spec\_hash commissions (that proof grades its spec against it next, and that grade is the chapter), and fully non-fatal (the diff still registers if grading fails). Set false to leave a system diff as a bare diff with no auto-graded envelope (an operator can still grade it on demand via POST /estate/migration-envelope/grade).

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__COMPARISON__AUTO_ENVELOPE`

#### `estate_char.comparison.envelope_backfill_on_startup`

When true, every backend restart sweeps the back catalogue of already-registered comparisons and auto-materializes a migration envelope for each forward diff that has none. Default FALSE, because that sweep is not free: each materialized envelope CREATES a spec\_conformance grading run, and a run created this way is indistinguishable from operator work downstream — it is counted into the Prover landing page's 'Live — N runs in progress' strip (which selects purely on status), and a comparison with no authored spec opens it as its grade ('No specification attached yet'). A boot creating a batch of runs nobody started is confusing at best and misleading at worst. This knob is INDEPENDENT of estate\_char.comparison.auto\_envelope, which still governs whether a comparison gets an envelope at all (fired per-diff at diff completion, where it is part of operator-initiated work). Set true as a deliberate one-off maintenance action to bring pre-existing comparisons up to the full five-beat replay — the runs it mints are then legitimately your own — then set it back to false.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__ESTATE_CHAR__COMPARISON__ENVELOPE_BACKFILL_ON_STARTUP`

### estate\_char.estates

#### `estate_char.estates.scan_drift_enabled`

When true (default), after a source re-scan finishes, compute a same-engine scan-over-scan drift delta (the new snapshot vs the estate's previous finished snapshot) and store the compact 'what changed since last time' line on the timeline row. Same dialect on both sides means zero representation noise, so every element is a genuine temporal change. Costs one extra same-engine mediated diff per re-scan; failure is non-fatal (the scan still finishes). Set false to skip the drift delta entirely (the scan timeline still records every scan).

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__ESTATES__SCAN_DRIFT_ENABLED`

### estate\_char.episodes

#### `estate_char.episodes.auto_open`

When true, a spec-conformance grading run that finishes DIRTY (implementer-actionable findings) automatically opens a reconciliation episode from its findings, superseding the scope's prior open episode (one open episode per scope). Default false per the recorded Q3 decision: opening is an explicit action ('Start reconciliation' in the Prover GUI, the /estate/episodes/open route, or an orchestrator call); bench/CI contexts that drive the loop unattended set this true. Auto-opened episodes record the party identities from estate\_char.episodes.implementer\_id / prover\_id. Best-effort: an auto-open failure is logged and never sinks the grading run.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__ESTATE_CHAR__EPISODES__AUTO_OPEN`

#### `estate_char.episodes.implementer_id`

The implementer-side party identity recorded on an episode when the opener does not name one (auto-open, or an explicit open without implementer\_id). The licensing doctrine is enforced against this identity: it can never appear as a licensor on the episode's findings. Set it to the actual coding-agent bot id in bench/CI contexts so slice-3 machine writes bind to the real party.

* **Type:** `str`
* **Default:** `"implementer-agent"`
* **Override:** `GENESIS__ESTATE_CHAR__EPISODES__IMPLEMENTER_ID`

#### `estate_char.episodes.prover_id`

The prover-side party identity recorded on an episode when the opener does not name one. The ONLY identity that may license a finding on the episode (the implementer proposes, never licenses). Set it to the actual prover/adjudicator bot id in bench/CI contexts so slice-3 machine writes bind to the real party.

* **Type:** `str`
* **Default:** `"prover-agent"`
* **Override:** `GENESIS__ESTATE_CHAR__EPISODES__PROVER_ID`

### estate\_char.rulings

#### `estate_char.rulings.enabled`

Master switch for the estate ruling library. OFF (default): the get\_estate\_leans / consult\_estate\_ruling tools return empty leans / all-escalate, the read\_rulings() compile seam returns \[], the promotion/seed hooks no-op, and the /estate/rulings routes serve empty worklists — byte-identical to the feature being absent until an operator opts in. ON: settled (class, jurisdiction) directions are served to spec compile and build-time consults.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__ESTATE_CHAR__RULINGS__ENABLED`

#### `estate_char.rulings.fairness_hold`

Marks this deployment a benchmark / fairness-controlled context: the ruling overlay is inert BY DESIGN even when estate\_char.rulings.enabled is true — read\_rulings() returns \[], get\_estate\_leans returns empty leans, consult\_estate\_ruling escalates every class without filing questions. A learned estate default is exactly the advantage a fresh installation lacks, so overlay resolution must never be active on a benchmark run (the spec-ambiguity taxonomy's overlay contract). Benchmark harnesses set this true; production estates leave it false.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__ESTATE_CHAR__RULINGS__FAIRNESS_HOLD`

#### `estate_char.rulings.seed_provisional_on_adjudication`

When true (and rulings.enabled is true), a prover adjudication 'agree' on a class-tagged episode issue also seeds a PROVISIONAL ruling in the estate ruling library — auto-applying but visibly provisional and queued for human ratification (the RATIFY gate). Licensor independence is enforced at the store seam: a seed whose prover equals the implementer, or whose identities are unconfigured defaults, is refused. Default OFF: adjudications change only the episode ledger until an operator opts into provisional seeding.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__ESTATE_CHAR__RULINGS__SEED_PROVISIONAL_ON_ADJUDICATION`

#### `estate_char.rulings.promote_on_human_license`

When true (and rulings.enabled is true), a human court ruling of 'license' on a class-tagged obligation finding also promotes the resolution to a settled (class, jurisdiction) direction in the estate ruling library, carrying the finding's evidence signature. Default OFF: auto-promoting every one-off license into a standing class-level convention risks over-generalization, so the explicit settle action is the preferred write path; enable only after field use shows the promotions match operator intent.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__ESTATE_CHAR__RULINGS__PROMOTE_ON_HUMAN_LICENSE`

### estate\_char.adjudicator

#### `estate_char.adjudicator.mode`

How adjudicator verdicts take effect. 'silent' (default, the adoption path): verdicts are persisted to the adjudication log with receipts and provenance, and NOTHING else changes — no dispositions staged, no flow altered; the log stays queryable for counterfactual scoring. 'active': a target\_defect verdict (and a pocket-mode candidate\_improvement, recorded as the builder order 'match the declared behaviour for now') is SENT BACK — applied to its finding at once under the adjudicator's name with an audit event, because a send-back keeps the finding open until a fresh comparison shows the fix and needs nobody's approval; every other routable verdict (spec\_defect / platform / instrument\_defect) would settle a difference without a fix, so it is staged as a disposition package through the existing propose/approve path and applied only when a human approves it — a human approving the package remains the only licensing act, and escalations (question / spec\_ambiguity) still only land in the log. A candidate\_improvement additionally writes an improvement-docket entry for human review and is NEVER licensed; in blocking mode its builder item is withheld entirely. An unrecognized value reads as 'silent' (fail-closed).

* **Type:** `str`
* **Default:** `"silent"`
* **Options:** `silent`, `active`
* **Override:** `GENESIS__ESTATE_CHAR__ADJUDICATOR__MODE`

### estate\_char.consult

#### `estate_char.consult.apply_mode`

What an ACCEPTED\_SUPPORTING ruling from the Prover Consult bot does to the comparison board. 'advisory': the ruling is recorded on the finding (a finding event carrying the ruling digest) and changes nothing — for agents bouncing an idea off the seat, and the one mode in which there is nothing to approve, so the approve/decline action refuses. 'human\_approval' (default): the ruling is recorded and the finding shows 'ruling pending approval'; it STAYS in the red (unlicensed) count and nothing is seeded until a human approves, which seeds and ratifies the recorded ruling in one action. 'auto': the ruling seeds a PROVISIONAL direction in the estate ruling library, under the consult\_ruling provenance, which applies immediately to that ambiguity class — the finding shows 'ruled — provisional' until a human ratifies it, and declining withdraws the direction the acceptance applied; bench and CI contexts set this. A decision names the exact ruling digest it read, so an approval that arrives after the finding was ruled on again is refused (409) rather than applied. A finding whose obligation carries no ambiguity class has no ruling slot to seed at all, so auto records the ruling and seeds nothing. In every mode the ruling library's own switches still govern what an AGENT may seed unattended: with estate\_char.rulings.enabled false or estate\_char.rulings.fairness\_hold true the ruling is recorded as a finding event only and no direction is seeded. An unrecognized value reads as 'advisory' (fail-closed).

* **Type:** `str`
* **Default:** `"human_approval"`
* **Options:** `advisory`, `human_approval`, `auto`
* **Override:** `GENESIS__ESTATE_CHAR__CONSULT__APPLY_MODE`

### estate\_char.reconcile

#### `estate_char.reconcile.stale_after_seconds`

Seconds a 'running' estatechar run/scan/self-drill row may go without a driver heartbeat before a startup reconcile treats it as orphaned and marks it error. A row whose heartbeat\_at (or, for a legacy row that never stamped one, started\_at) is within this window is left untouched as live-looking — this is what stops a backend restart from erroring a scan/run whose driver is still alive or that just started. HARD INVARIANT (GEN-2636): this MUST stay strictly greater than the longest legitimate silent interval, which is a full stimulus agent turn (estate\_char.stimulus.agent\_timeout\_seconds, 1800s) PLUS slack for a trailing server-side phase (run\_differential / verify\_\*) and heartbeat-write latency — otherwise a healthy long turn inside its own permitted budget is reapable mid-flight (the false-reap the default 900s caused: a turn observed reaped at 2365s). The default 2400s = 1800s agent budget + 600s slack (40 min); tests/critical/test\_estatechar\_reconcile\_margin.py fails the build if this margin ever re-inverts. Raise it further if a legitimate phase can go silent even longer between progress writes; do NOT lower it below agent\_timeout\_seconds + a few minutes.

* **Type:** `int`
* **Default:** `2400`
* **Override:** `GENESIS__ESTATE_CHAR__RECONCILE__STALE_AFTER_SECONDS`

#### `estate_char.reconcile.enabled`

Master switch for the PERIODIC estatechar stale-run/scan reconcile (F4). This is a lifecycle cleanup owner, not optional estate scanning: the startup pass can only reap rows orphaned before boot, while this timer terminalizes run, scan, and adjudication rows orphaned later in the same long-lived process. Default on so those shared rows cannot remain in a ghost 'running' state indefinitely.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__RECONCILE__ENABLED`

#### `estate_char.reconcile.interval_seconds`

Seconds between periodic estatechar stale-run/scan reconcile passes when estate\_char.reconcile.enabled is true. Each pass is one indexed SELECT over 'running' rows plus an UPDATE only for those proven stale by heartbeat, so it is cheap; the default 300 keeps the 'Live' feed honest within five minutes plus the stale\_after\_seconds window. Set \<= 0 to skip registering the job entirely (startup reconcile still runs).

* **Type:** `int`
* **Default:** `300`
* **Override:** `GENESIS__ESTATE_CHAR__RECONCILE__INTERVAL_SECONDS`

### estate\_char.shutdown

#### `estate_char.shutdown.drain_timeout_seconds`

Seconds the shutdown drain waits for in-flight estatechar background runs before terminalizing the stragglers' rows and continuing teardown. The 30s default is sized for the short flows (preflight, a differential), NOT for an agentic seat: a Prover Spec Registrar seat run takes 20-40 minutes on a 26-table spec, so any restart cancels authoring essentially every time and the row is written failed with a shutdown basis. Raising it does NOT make a seat survive a restart — it only buys a longer wait, and the whole budget is spent inside the host's graceful-shutdown window, past which the process is killed and the flows that WOULD have finished die mid-write too. Raise it only if your deployment's shutdown grace period is longer and you would rather wait than terminalize.

* **Type:** `int`
* **Default:** `30`
* **Override:** `GENESIS__ESTATE_CHAR__SHUTDOWN__DRAIN_TIMEOUT_SECONDS`

### estate\_char.assurance

#### `estate_char.assurance.enabled`

Master switch for the scheduler-driven continuous-assurance loop that re-characterizes each sealed source contract's estate and records deviations. Default off: no background re-verification until an operator opts in.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__ESTATE_CHAR__ASSURANCE__ENABLED`

#### `estate_char.assurance.interval_seconds`

Seconds between assurance cycles when estate\_char.assurance.enabled is true. Each cycle re-characterizes every sealed contract's estate, so size this to the estates' scan cost. Set \<= 0 to skip registering the job entirely.

* **Type:** `int`
* **Default:** `3600`
* **Override:** `GENESIS__ESTATE_CHAR__ASSURANCE__INTERVAL_SECONDS`

#### `estate_char.assurance.resolve_after`

Number of consecutive passing assurance cycles after which an open estate deviation is aged out as resolved (transient drift).

* **Type:** `int`
* **Default:** `3`
* **Override:** `GENESIS__ESTATE_CHAR__ASSURANCE__RESOLVE_AFTER`

#### `estate_char.assurance.escalate_after`

Number of consecutive failing assurance cycles a deviation must persist before it is escalated for operator triage.

* **Type:** `int`
* **Default:** `3`
* **Override:** `GENESIS__ESTATE_CHAR__ASSURANCE__ESCALATE_AFTER`

#### `estate_char.assurance.bot_id`

Acting identity used for assurance re-characterization queries against source connections.

* **Type:** `str`
* **Default:** `"system"`
* **Override:** `GENESIS__ESTATE_CHAR__ASSURANCE__BOT_ID`

### estate\_char.attestation

#### `estate_char.attestation.signing_key`

Base64-encoded raw-32 Ed25519 private key used to sign exported estate attestations into DSSE-style envelopes. Resolved ONLY inside the attest (verifier) workflow -- doer-side execution tools never receive it. Leave unset to export unsigned attestations.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__ESTATE_CHAR__ATTESTATION__SIGNING_KEY`
* **Secret**

#### `estate_char.attestation.key_id`

Opaque key identifier stamped into signed attestation envelopes (the DSSE keyid hint) so third-party verifiers can pick the matching public key.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__ESTATE_CHAR__ATTESTATION__KEY_ID`

### estate\_char.knowledge

#### `estate_char.knowledge.enabled`

Master switch for the Genesis Knowledge System collector job that harvests abstracted, provenance-tagged KnowledgeAtoms from the estate corpus (mediated diffs, jitter/arsenal campaigns, field survival, foundry campaigns). Default off: no background collection until an operator opts in. Paused-at-startup when off so it can be resumed from the Pulse UI without a redeploy.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__ESTATE_CHAR__KNOWLEDGE__ENABLED`

#### `estate_char.knowledge.collector_interval_seconds`

Seconds between Genesis Knowledge System collection sweeps. Default 0 disables the job entirely (nothing is registered). Set > 0 to have the collector periodically re-derive the knowledge corpus from current store state (idempotent: unchanged evidence is a no-op; new evidence supersedes the prior lineage head).

* **Type:** `int`
* **Default:** `0`
* **Override:** `GENESIS__ESTATE_CHAR__KNOWLEDGE__COLLECTOR_INTERVAL_SECONDS`

### estate\_char.fault\_drill

#### `estate_char.fault_drill.run_on_scan_default`

When a fresh source scan compiles a draft contract, whether to also run the STATIC fault-drill coverage meter on that same background run. Default FALSE: the campaign enumerates a drill per obligation AND per structural fact while each drill re-runs self-verification over the whole characterization, so it is quadratic in estate size and adds tens of minutes to a large scan. Most of what it proves is tautological -- the contract is compiled from the same characterization the drill mutates, so mutating a fact the contract asserts directly fails verification by construction. Its genuinely valuable output (blind spots: mutations that SURVIVE) is a property of the obligation VOCABULARY, which changes when new obligation families ship, not per customer scan. Set true to put the meter back on every scan. Turning it off never disables the drill itself: an operator can still run it deliberately per contract, and the on-demand hardening round always drills.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__ESTATE_CHAR__FAULT_DRILL__RUN_ON_SCAN_DEFAULT`

#### `estate_char.fault_drill.max_drills`

Sampling cap on the number of drills one coverage run scores. The default 250 keeps a drill bounded and fast on any estate. A positive value keeps the first N drills (deterministic sorted order) and DROPS the rest; the dropped count and the classes affected are logged, recorded in the report as dropped\_drills/dropped\_note, and carried into the run summary, so a capped coverage number is never mistaken for a complete one. Set 0 for NO cap -- every element of the contract surface is drilled, which is quadratic in estate size and is what made a 540-object estate drill for over 35 minutes.

* **Type:** `int`
* **Default:** `250`
* **Override:** `GENESIS__ESTATE_CHAR__FAULT_DRILL__MAX_DRILLS`

### estate\_char.fault\_drill.classes

#### `estate_char.fault_drill.classes.not_null`

Include NOT NULL drills (inject a null into each not-null column) in the coverage run.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__FAULT_DRILL__CLASSES__NOT_NULL`

#### `estate_char.fault_drill.classes.check`

Include CHECK / value-range drills (push each bounded column past its frozen min/max) in the coverage run.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__FAULT_DRILL__CLASSES__CHECK`

#### `estate_char.fault_drill.classes.type_param`

Include type-parameter drills (perturb each column's declared precision/length/scale) in the coverage run. Typically a blind spot: no obligation family re-derives declared column types.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__FAULT_DRILL__CLASSES__TYPE_PARAM`

#### `estate_char.fault_drill.classes.default`

Include column-default drills (drop/alter each declared DEFAULT) in the coverage run. Typically a blind spot: no obligation family re-derives declared defaults.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__FAULT_DRILL__CLASSES__DEFAULT`

#### `estate_char.fault_drill.classes.foreign_key`

Include foreign-key drills (orphan each referential obligation and each measured foreign key) in the coverage run.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__FAULT_DRILL__CLASSES__FOREIGN_KEY`

#### `estate_char.fault_drill.classes.unique`

Include unique/index-key drills (drop each declared unique key, duplicate a row under each measured unique key) in the coverage run.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__FAULT_DRILL__CLASSES__UNIQUE`

#### `estate_char.fault_drill.classes.index`

Include index drills (drop each declared index) in the coverage run.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__FAULT_DRILL__CLASSES__INDEX`

#### `estate_char.fault_drill.classes.presence`

Include presence drills (drop each column and each table) in the coverage run.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__FAULT_DRILL__CLASSES__PRESENCE`

#### `estate_char.fault_drill.classes.value`

Include value-domain drills (perturb each categorical column's measured domain) in the coverage run.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__FAULT_DRILL__CLASSES__VALUE`

#### `estate_char.fault_drill.classes.access`

Include access-ceiling drills (widen the acting principal's grant on each object with an access-ceiling obligation) in the coverage run.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__FAULT_DRILL__CLASSES__ACCESS`

### estate\_char.source\_hardening

#### `estate_char.source_hardening.enabled`

Master switch for the source-hardening self-drill workflow. Default off: the \~hour-long adversarial round only runs when an operator opts in (at source seal or on demand). The static coverage meter (estate\_char.fault\_drill) is the fast deterministic tier and is itself off the scan path by default; this is the creative discovery tier.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__ESTATE_CHAR__SOURCE_HARDENING__ENABLED`

#### `estate_char.source_hardening.run_on_seal_default`

When the self-drill is enabled, whether a source seal recommends running a hardening round by default (recommended-but-skippable). Only consulted when estate\_char.source\_hardening.enabled is true. Set false to make hardening purely on-demand even where enabled.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__SOURCE_HARDENING__RUN_ON_SEAL_DEFAULT`

#### `estate_char.source_hardening.run_on_scan_default`

When a fresh source scan compiles a draft contract, whether to automatically chain the adversarial self-drill hardening round on the SAME background run (contract, then the static fault drill if estate\_char.fault\_drill.run\_on\_scan\_default is on, then adversarially harden). Default true (operator directive: harden by default, skippable). Set false to make the adversarial round on-demand only. This knob governs ONLY the adversarial round; the static fault-drill coverage meter has its own gate at estate\_char.fault\_drill.run\_on\_scan\_default. The round is additionally skipped, with a recorded reason, when the source dialect is not one the live clone/mutator supports (postgres only today) -- it never fails the run.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__SOURCE_HARDENING__RUN_ON_SCAN_DEFAULT`

#### `estate_char.source_hardening.adversary_runner`

Which pluggable adversary the workflow injects: 'scripted' (the deterministic reference alteration set -- no agent, proves the pipeline), 'genesis' (an in-product Genesis agent with the estate tool groups), or 'claude\_code' (an external Claude Code agent). Same clone->seal->assess->score protocol regardless; the deployment picks whichever it has. On the LIVE drill 'claude\_code' shells out to the external agent CLI and falls back to the deterministic AutoAdversary (with a recorded reason) on any failure, so enabling it can never abort a drill; 'genesis' remains a documented integration point that likewise falls back. The default stays deterministic -- agentic runners are opt-in.

* **Type:** `str`
* **Default:** `"scripted"`
* **Override:** `GENESIS__ESTATE_CHAR__SOURCE_HARDENING__ADVERSARY_RUNNER`

#### `estate_char.source_hardening.difficulty`

Which deterministic adversary TIER the drill plants: 'standard' (the AutoAdversary's 11-defect frontier set, each sitting on an instrument the sealed contract already carries) or 'hard' (the HardAdversary -- novel faults planted on measured facts the BASE contract freezes no obligation for, so they provably SLIP the base contract, route to an antibody, and are only caught on a re-drill after the covering digest instrument is hardened in). 'hard' is the reproducible slip->harden->defend demonstrator. Composes with adversary\_runner: an agentic runner ('claude\_code'/'genesis') uses the tier's adversary as its deterministic fallback. Read at call time.

* **Type:** `str`
* **Default:** `"standard"`
* **Override:** `GENESIS__ESTATE_CHAR__SOURCE_HARDENING__DIFFICULTY`

#### `estate_char.source_hardening.knowledge_weighting`

Whether a live self-drill biases WHICH defects it plants toward the fault classes already known-common for this estate/platform pair (ISS12 adversary feedback). When on, the adversary reads the antibody ledger (fault classes that evaded before, class-wide or on this source) and the ISS11 knowledge dossiers (difference patterns seen on this engine pair) at run start and stable-sorts its defect set by those weights BEFORE any max\_alterations cap, so historically-common failures are prioritized to be included. This only BIASES ordering -- it never excludes a fault class and always keeps the negative control, so a capped drill still explores the whole catalog's floor; an uncapped drill is unaffected except for defect order. Determinism holds: the weights are a snapshot pinned at run start (a pure function of stored knowledge then), so a drill is byte-reproducible given the same knowledge snapshot + seed. Set false to run the classic uniform, knowledge-blind selection. Read at call time.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__SOURCE_HARDENING__KNOWLEDGE_WEIGHTING`

#### `estate_char.source_hardening.adversary_timeout_seconds`

Wall-clock ceiling for one invocation of the agentic adversary CLI ('claude\_code' runner). A blind external agent alters the throwaway clone and returns an alteration manifest; if it exceeds this many seconds the invocation is killed and the drill falls back to the deterministic AutoAdversary with a recorded reason. Only consulted when adversary\_runner='claude\_code'. Read at call time.

* **Type:** `int`
* **Default:** `1800`
* **Override:** `GENESIS__ESTATE_CHAR__SOURCE_HARDENING__ADVERSARY_TIMEOUT_SECONDS`

#### `estate_char.source_hardening.max_alterations`

Cap on the number of alterations one drill applies. 0 (the default) means NO cap -- the adversary applies its full set. A positive value keeps the first N (deterministic order) and drops the rest; the dropped count is recorded so a capped run is never mistaken for a full one.

* **Type:** `int`
* **Default:** `0`
* **Override:** `GENESIS__ESTATE_CHAR__SOURCE_HARDENING__MAX_ALTERATIONS`

#### `estate_char.source_hardening.target_alterations`

How many novel DEFECTS the agentic adversary ('claude\_code'/'genesis' runner) is asked to invent and plant per live drill -- the blind agent aims for this many real, catch-worthy changes. Clamped to \[5, 50] at call time, so a mis-set value can never request an absurd or empty drill. Distinct from max\_alterations (a hard post-hoc cap on the DETERMINISTIC tier's fixed set); this shapes how many changes the AGENT creates, letting different runs plant different-sized change sets. Only consulted for an agentic runner; the deterministic tiers ignore it. Read at call time.

* **Type:** `int`
* **Default:** `12`
* **Override:** `GENESIS__ESTATE_CHAR__SOURCE_HARDENING__TARGET_ALTERATIONS`

#### `estate_char.source_hardening.negative_controls`

How many equivalence-preserving negative controls the agentic adversary ('claude\_code'/'genesis' runner) is asked to include per live drill -- changes that re-express data WITHOUT altering content (a pure physical row re-ordering or a rewrite that stores identical values), each on an object it does NOT otherwise alter and flagged is\_control. A flag on ANY of them is a false positive, so this sets how many independent false-positive probes each agentic run carries. Clamped to \[0, 20]. Only consulted for an agentic runner (the deterministic tiers use include\_negative\_control for their single built-in control). Read at call time.

* **Type:** `int`
* **Default:** `3`
* **Override:** `GENESIS__ESTATE_CHAR__SOURCE_HARDENING__NEGATIVE_CONTROLS`

#### `estate_char.source_hardening.include_negative_control`

Whether each drill includes a pure row-permutation negative control (an untouched table whose content multiset is byte-identical). The one property a sloppy comparator fails -- flagging it is a false positive. Keep on so every run measures false-positive rate honestly.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__SOURCE_HARDENING__INCLUDE_NEGATIVE_CONTROL`

#### `estate_char.source_hardening.escalate_after`

Number of times an evasion (a missed fault class / source weak spot) must recur across self-drill runs before its antibody is escalated for operator triage.

* **Type:** `int`
* **Default:** `3`
* **Override:** `GENESIS__ESTATE_CHAR__SOURCE_HARDENING__ESCALATE_AFTER`

#### `estate_char.source_hardening.resolve_after`

Number of consecutive self-drill runs that CATCH a previously-evaded fault class after which its open antibody ages out to resolved (the taxonomy grew the competency and it stuck).

* **Type:** `int`
* **Default:** `3`
* **Override:** `GENESIS__ESTATE_CHAR__SOURCE_HARDENING__RESOLVE_AFTER`

#### `estate_char.source_hardening.bot_id`

Acting identity used for the clone, mutation and blind-assessment queries a self-drill runs against the source and its throwaway clone.

* **Type:** `str`
* **Default:** `"system"`
* **Override:** `GENESIS__ESTATE_CHAR__SOURCE_HARDENING__BOT_ID`

### estate\_char.spec\_conformance

#### `estate_char.spec_conformance.target_items`

How many DISTINCT change items the specifier agent is asked to put in one spec -- the migration's change budget. Clamped to \[5, 50] at call time, so a mis-set value can never request an absurd or empty spec. Each item is one closed-enum change (add\_column, transform\_values, add\_derived\_mart, drop\_constraint, ...) at a column- or object-grain locus. Larger specs stress detection coverage and adjudication over more surface; smaller specs are the cheap de-risk size. Read at call time.

* **Type:** `int`
* **Default:** `12`
* **Override:** `GENESIS__ESTATE_CHAR__SPEC_CONFORMANCE__TARGET_ITEMS`

#### `estate_char.spec_conformance.specifier_mode`

The SPECIFIER agent's temperament, one of 'realistic' (default) or 'adversarial'. 'realistic' asks for the changes a competent team would make. 'adversarial' additionally biases the (still-blind) specifier brief toward the FRONTIER fault classes P1 showed realistic specs never produce -- compensated/multiset-preserving row-pairing changes, within-sampling-tolerance value shifts, boundary/rounding changes, and case-folding on un-instrumented columns -- every item still SPECCED with a concrete locus + expected\_effect and faithfully implementable, just realised so only a strong whole-row / full-content instrument sees them. Adversarial mode produces the hard-row data for the calibration certificate (any prover\_detection\_gap / prover\_granularity\_gap adjudications). The specifier stays blind to the prover/grader either way. An unrecognised value falls back to 'realistic'. Read at call time by the eval CLI.

* **Type:** `string`
* **Default:** `"realistic"`
* **Override:** `GENESIS__ESTATE_CHAR__SPEC_CONFORMANCE__SPECIFIER_MODE`

#### `estate_char.spec_conformance.nested_timeout_seconds`

Wall-clock ceiling for EACH nested `claude` invocation (the specifier, the implementer, and each judge classification). On timeout the specifier retries once at half the item target and the implementer retries once; a persistent hang stops with a recorded reason rather than an indefinite wait. The judge is best-effort -- a judge timeout leaves that discrepancy deferred (reported unadjudicated) rather than aborting the run. Read at call time.

* **Type:** `int`
* **Default:** `600`
* **Override:** `GENESIS__ESTATE_CHAR__SPEC_CONFORMANCE__NESTED_TIMEOUT_SECONDS`

#### `estate_char.spec_conformance.judge_enabled`

Whether the nested judge agent adjudicates the AMBIGUOUS remainder of discrepancies (oracle-indeterminate spec items and drift on derived objects) that the deterministic rules leave open. When false, those discrepancies stay in the 'unadjudicated' bucket and only the deterministically-decided buckets are populated -- useful for a fully offline / no-agent grading pass. The deterministic majority is decided either way. Read at call time.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__SPEC_CONFORMANCE__JUDGE_ENABLED`

#### `estate_char.spec_conformance.dialogue_enabled`

Whether AMBIGUOUS spec-item discrepancies (deterministic rules abstained) are adjudicated by the bounded 2-round grader\<->specifier DIALOGUE instead of the solo judge. Round 1 the grader states a blind plain-language framing + its tentative prover-side candidate bucket; round 2 the SPECIFIER agent (a fresh, still-blind nested invocation given only its own item) defends the item as well-formed or concedes its ambiguity; the grader issues the final bucket (concede => spec\_ambiguity, defend => the prover candidate) recording both positions. Any dialogue failure/timeout degrades that one discrepancy to the solo judge, so a stalled exchange never sinks a run. When false, the solo judge adjudicates the remainder as before. Gated by judge\_enabled (no agent adjudication at all when that is off). Read at call time.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__SPEC_CONFORMANCE__DIALOGUE_ENABLED`

#### `estate_char.spec_conformance.dialogue_timeout_seconds`

Hard wall-clock ceiling for EACH nested dialogue call (the specifier's defend-or-concede response). On timeout the dialogue degrades to the solo judge for that discrepancy rather than waiting indefinitely. Kept below nested\_timeout\_seconds so a dialogue round cannot outlast the primary agent budget. Read at call time.

* **Type:** `int`
* **Default:** `480`
* **Override:** `GENESIS__ESTATE_CHAR__SPEC_CONFORMANCE__DIALOGUE_TIMEOUT_SECONDS`

#### `estate_char.spec_conformance.persist_artifacts`

Whether an on-demand spec drill persists its comparison artifacts (the byte-identical baseline snapshot, the migrated clone's measured snapshot, and the blind mediated diff between them) plus two synthetic utility-kind estate identities ('\<estate> — spec-drill source' and '\<estate> (drill clone)'), exactly as a normal comparison persists them, so the theater renders the drill as a first-class two-circle comparison with the unseal re-sort on the canvas. The clone databases still tear down; only the measurement artifacts survive. When false, a drill persists only its graded run-view summary (the legacy panel-only report). Additive: runs whose artifacts were never persisted keep the panel-only view regardless. Read at call time.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__SPEC_CONFORMANCE__PERSIST_ARTIFACTS`

### estate\_char.behavioral

#### `estate_char.behavioral.sandbox_statement_timeout_seconds`

Wall-clock ceiling applied to each statement a behavioral trajectory adapter (Snowflake/ClickHouse) runs inside its throwaway `_stim`/`_eval` sandbox clone -- issued as Snowflake ALTER SESSION SET STATEMENT\_TIMEOUT\_IN\_SECONDS and ClickHouse SETTINGS max\_execution\_time. A safety envelope so a runaway sandbox transform cannot hold a warehouse open indefinitely; it never touches a live estate (the adapters only ever write to the sandbox). Read at call time; set \<= 0 to leave the engine default in place.

* **Type:** `int`
* **Default:** `900`
* **Override:** `GENESIS__ESTATE_CHAR__BEHAVIORAL__SANDBOX_STATEMENT_TIMEOUT_SECONDS`

#### `estate_char.behavioral.dbt_cloud_lifecycle_connection_ref`

Non-secret pointer to the dedicated Genesis GCP connection used to allocate and clean up dbt Cloud-to-BigQuery campaign resources. The actual service-account credential remains in Genesis Connections and must never be stored in APP\_CONFIG. Empty (the default) fails closed: no runtime authority lease can be issued. Read at call time.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__ESTATE_CHAR__BEHAVIORAL__DBT_CLOUD_LIFECYCLE_CONNECTION_REF`

#### `estate_char.behavioral.dbt_cloud_lifecycle_principal`

Expected GCP service-account email for the dbt Cloud-to-BigQuery lifecycle connection. This is an identity pin, not a credential; the actual credential remains in Genesis Connections. Empty (the default) fails closed: no runtime authority lease can be issued. Read at call time.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__ESTATE_CHAR__BEHAVIORAL__DBT_CLOUD_LIFECYCLE_PRINCIPAL`

#### `estate_char.behavioral.dbt_cloud_grader_connection_ref`

Non-secret pointer to the dedicated Genesis BigQuery connection used to grade dbt Cloud campaign outputs. The actual service-account credential remains in Genesis Connections and must never be stored in APP\_CONFIG. Empty (the default) fails closed: no runtime authority lease can be issued. Read at call time.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__ESTATE_CHAR__BEHAVIORAL__DBT_CLOUD_GRADER_CONNECTION_REF`

#### `estate_char.behavioral.dbt_cloud_grader_principal`

Expected GCP service-account email for the dbt Cloud-to-BigQuery grader connection. This is an identity pin, not a credential; the actual credential remains in Genesis Connections. Empty (the default) fails closed: no runtime authority lease can be issued. Read at call time.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__ESTATE_CHAR__BEHAVIORAL__DBT_CLOUD_GRADER_PRINCIPAL`

#### `estate_char.behavioral.dbt_cloud_grader_control_dataset`

Fully qualified project.dataset identity of the standing grader-control dataset used by dbt Cloud-to-BigQuery authority probes. Empty (the default) fails closed. Runtime composition requires it to be in the configured warehouse project and distinct from every run-owned and comparison-arm dataset. Read at call time.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__ESTATE_CHAR__BEHAVIORAL__DBT_CLOUD_GRADER_CONTROL_DATASET`

#### `estate_char.behavioral.dbt_cloud_other_arm_dataset`

Fully qualified project.dataset identity of the standing comparison-arm dataset the dbt runner must be unable to read. Empty (the default) fails closed. Runtime composition requires it to be in the configured warehouse project and distinct from every run-owned and grader-control dataset. Read at call time.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__ESTATE_CHAR__BEHAVIORAL__DBT_CLOUD_OTHER_ARM_DATASET`

#### `estate_char.behavioral.dbt_cloud_runtime_enabled`

Whether dbt Cloud-to-BigQuery runtime composition may allocate resources and issue execution authority. The default is false so dormant groundwork cannot be activated accidentally; cleanup recovery remains independently controlled and continues even while execution is disabled. Read at call time.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__ESTATE_CHAR__BEHAVIORAL__DBT_CLOUD_RUNTIME_ENABLED`

#### `estate_char.behavioral.dbt_cloud_runtime_cleanup_enabled`

Whether the dedicated dbt Cloud runtime cleanup owner runs immediately when the backend scheduler starts and periodically thereafter. This safety reconciler is independent of stale estate-run reconciliation so disabling an unrelated job cannot strand durable runtime resources. Read at scheduler registration.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__BEHAVIORAL__DBT_CLOUD_RUNTIME_CLEANUP_ENABLED`

#### `estate_char.behavioral.dbt_cloud_runtime_cleanup_interval_seconds`

Interval in seconds for the dedicated dbt Cloud runtime cleanup owner after its immediate startup pass. Accepted range is 10-3600 seconds; default 60. Read at scheduler registration.

* **Type:** `int`
* **Default:** `60`
* **Minimum:** `10`
* **Maximum:** `3600`
* **Override:** `GENESIS__ESTATE_CHAR__BEHAVIORAL__DBT_CLOUD_RUNTIME_CLEANUP_INTERVAL_SECONDS`

#### `estate_char.behavioral.dbt_cloud_runtime_lease_ttl_seconds`

Lifetime in seconds of a qualified dbt Cloud-to-BigQuery runtime authority lease. A short bounded lease limits stale resource and identity authority; 60-3600 seconds is accepted and 900 seconds is the conservative default. A lease is never authority by itself after it expires. Read at call time.

* **Type:** `int`
* **Default:** `900`
* **Minimum:** `60`
* **Maximum:** `3600`
* **Override:** `GENESIS__ESTATE_CHAR__BEHAVIORAL__DBT_CLOUD_RUNTIME_LEASE_TTL_SECONDS`

#### `estate_char.behavioral.dbt_cloud_terminal_timeout_seconds`

Wall-clock ceiling for proving one dbt Cloud run terminal during qualification, execution, or cleanup recovery. Runtime composition refuses a value longer than the authority lease TTL so polling cannot silently outlive its lease. Accepted range is 60-3600 seconds; default 900. Read at call time.

* **Type:** `int`
* **Default:** `900`
* **Minimum:** `60`
* **Maximum:** `3600`
* **Override:** `GENESIS__ESTATE_CHAR__BEHAVIORAL__DBT_CLOUD_TERMINAL_TIMEOUT_SECONDS`

#### `estate_char.behavioral.drill_connection_id`

Registered connection id naming the Postgres server that hosts the behavioral drill pair (the persisted source clone + target clone the legacy bench injects into). The bench resolves host/port/user/password through the connections layer for this id -- Prover never reads a password from the process environment and ships no default credential. Unset (the default) is a stated refusal: the bench fails fast with 'no drill connection configured', it never falls back to a guessed local server. Point it at a throwaway drill server only; the bench mutates and restores rows on both databases. Read at call time.

* **Type:** `string`
* **Default:** `""`
* **Override:** `GENESIS__ESTATE_CHAR__BEHAVIORAL__DRILL_CONNECTION_ID`

#### `estate_char.behavioral.source_database`

Database name of the SOURCE side of the behavioral drill pair on the drill connection's server. The default reproduces the original shopbench drill clone so an existing drill server keeps working unchanged. A caller that already knows the pair (the stimulus legacy-bench executor, which reads the clone names off the comparison scope) passes them explicitly and this field is not consulted. Read at call time.

* **Type:** `string`
* **Default:** `"sbp4b_24cdd72f"`
* **Override:** `GENESIS__ESTATE_CHAR__BEHAVIORAL__SOURCE_DATABASE`

#### `estate_char.behavioral.target_database`

Database name of the TARGET side of the behavioral drill pair on the drill connection's server. The default reproduces the original shopbench drill clone; see estate\_char.behavioral.source\_database for when it is consulted. Read at call time.

* **Type:** `string`
* **Default:** `"sbp4w_24cdd72f"`
* **Override:** `GENESIS__ESTATE_CHAR__BEHAVIORAL__TARGET_DATABASE`

#### `estate_char.behavioral.audit_dir`

Directory the behavioral bench writes its durable JSON evidence artifact into (behavioral-test-p1.json). A relative path is resolved against the process working directory, which reproduces the previous behaviour; set an absolute path to pin the evidence somewhere the process cannot lose it. Created if absent. Read at call time.

* **Type:** `string`
* **Default:** `"prover_audit"`
* **Override:** `GENESIS__ESTATE_CHAR__BEHAVIORAL__AUDIT_DIR`

#### `estate_char.behavioral.mechanism_sql_path`

Optional path to a persisted spec-conformance run-view JSON whose implementer mechanism\_sql supplies the TARGET mart derivations, preferred over the bench's own empirical recovery and still gated by the same byte-identity self-check. Empty (the default) means use the recovered fallback -- exactly the pre-ISS24 behaviour. An absent or unreadable file also falls back, with a logged warning. Read at call time.

* **Type:** `string`
* **Default:** `""`
* **Override:** `GENESIS__ESTATE_CHAR__BEHAVIORAL__MECHANISM_SQL_PATH`

#### `estate_char.behavioral.use_agent_designer`

Whether the behavioral bench's standalone entry point asks a nested agent CLI to design the edge batch before falling back to the deterministic batch. True (the default) preserves the original standalone behaviour; false keeps a bench run reproducible with no nested agent. Callers that drive the bench programmatically (the legacy-bench stimulus executor) pass use\_agent explicitly and this field is not consulted. Read at call time.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__BEHAVIORAL__USE_AGENT_DESIGNER`

### estate\_char.self\_drill

#### `estate_char.self_drill.connection_id`

Registered connection id naming the Postgres server the self-drill creates its throwaway clone pair on. Host, port, user and password are resolved through the connections layer for this id at connect time -- Prover reads no PG\* environment variable and ships no default credential. Unset (the default) is a stated refusal: a drill that needs to connect fails fast with 'no drill connection configured', it never falls back to a guessed local server. The drill CREATEs and DROPs databases on this server, so it must be a throwaway drill server and the connection's role needs CREATEDB. Read at call time.

* **Type:** `string`
* **Default:** `""`
* **Override:** `GENESIS__ESTATE_CHAR__SELF_DRILL__CONNECTION_ID`

#### `estate_char.self_drill.admin_database`

Maintenance database the self-drill connects to in order to CREATE and DROP its clone databases (a Postgres session cannot drop the database it is connected to). 'postgres' is the standard maintenance database present on every server; change it only for a server that does not have one. Read at call time.

* **Type:** `string`
* **Default:** `"postgres"`
* **Override:** `GENESIS__ESTATE_CHAR__SELF_DRILL__ADMIN_DATABASE`

#### `estate_char.self_drill.databricks_enabled`

Whether a spec drill may run on Databricks (estatechar.genesis\_integration.self\_drill\_live.DatabricksDrillRuntime). False (the default) is a stated refusal: the spec-drill endpoint refuses a Databricks estate with a 400 exactly as before, and constructing the Databricks drill runtime fails with an error naming this field, before any connection is resolved. When true AND databricks\_base\_catalog, databricks\_work\_catalog and databricks\_connection\_id are all set, the spec-drill endpoint (and so Eve) admits a Databricks estate and runs the drill on the two scratch catalogs through databricks\_connection\_id, never through the estate's own connection. Read at call time.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__ESTATE_CHAR__SELF_DRILL__DATABRICKS_ENABLED`

#### `estate_char.self_drill.databricks_base_catalog`

The pre-made Unity Catalog scratch catalog that holds a Databricks spec drill's pristine BASE side. Every drill drops and recreates the schemas raw and marts inside it, and touches nothing else, so it must be a throwaway catalog the drill principal holds CREATE SCHEMA on. The name must be lower-case letters, digits and underscores, start with a letter, carry the sandbox token 'sd' as its own underscore-separated word (for example ulta\_drill\_sd\_base), and differ from databricks\_work\_catalog. Empty (the default) refuses the Databricks drill runtime. Only one Databricks drill may run at a time, because every drill reuses this catalog. Read at call time.

* **Type:** `string`
* **Default:** `""`
* **Override:** `GENESIS__ESTATE_CHAR__SELF_DRILL__DATABRICKS_BASE_CATALOG`

#### `estate_char.self_drill.databricks_work_catalog`

The pre-made Unity Catalog scratch catalog that holds a Databricks spec drill's WORK side, the one the implementer migrates. Same rules as databricks\_base\_catalog: throwaway, CREATE SCHEMA granted, only raw and marts are dropped and recreated inside it, lower-case with the 'sd' sandbox token, and different from the base catalog. Empty (the default) refuses the Databricks drill runtime. Read at call time.

* **Type:** `string`
* **Default:** `""`
* **Override:** `GENESIS__ESTATE_CHAR__SELF_DRILL__DATABRICKS_WORK_CATALOG`

#### `estate_char.self_drill.databricks_connection_id`

Registered connection id of the Genesis Databricks connection every Databricks spec drill runs through. A reference to a connection, not a credential: the host, warehouse and token are resolved through the connections layer at connect time. Its principal must be the dedicated drill principal, granted rights on databricks\_base\_catalog and databricks\_work\_catalog and on no other catalog, because those grants are what contain the implementer's SQL (a three-part name reaches any catalog the principal can write). The drill seeds its own data and never reads the estate's tables, so it never uses the drilled estate's own connection, even when that connection is Databricks too. Empty (the default) keeps Databricks estates refused by the spec-drill endpoint. Read at call time.

* **Type:** `string`
* **Default:** `""`
* **Override:** `GENESIS__ESTATE_CHAR__SELF_DRILL__DATABRICKS_CONNECTION_ID`

### estate\_char.stimulus

#### `estate_char.stimulus.enabled`

Master switch for the first-class stimulus run kind and its authed trigger (POST /api/estate/stimulus/run). When true (default) the RATIFY-gated endpoint accepts a submit-and-poll stimulus run against a comparison and records a real run row with persisted per-step evidence + a summary artifact. When false the endpoint refuses (409/400) and no stimulus run can be commissioned. Does NOT auto-fire stimulus from the diff seam -- that wiring is a separate, later decision; this flag only governs whether an operator/agent may trigger a stimulus run at all.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__STIMULUS__ENABLED`

#### `estate_char.stimulus.default_executor`

Which registered stimulus EXECUTOR a run uses when the caller does not name one. The executor is the pluggable seam that performs the open-ended agentic parts (design the synthetic batch, run the ETLs on both sides); the deterministic oracle/verdict live in the run driver, never in the executor. The product-native executor is a commissioned Genesis agent mission ('genesis-agent', the intended default). The programmatic shopbench path ('legacy-bench') is a clearly-labeled bench executor for plumbing verification only and is NEVER selected implicitly -- a caller must name it explicitly. An unknown/unregistered name fails the run fast with a clear error rather than silently degrading. Read at call time.

* **Type:** `string`
* **Default:** `"genesis-agent"`
* **Override:** `GENESIS__ESTATE_CHAR__STIMULUS__DEFAULT_EXECUTOR`

#### `estate_char.stimulus.agent_bot_id`

The Genesis bot the genesis-agent executor commissions to design + execute a stimulus run. Default 'Eve' (the general agent, in the registry's canonical case -- the bot lookup and connection grants are matched case-insensitively, but commissioning the canonical-case id avoids any case-sensitive bot resolution) -- there is deliberately NO dedicated stimulus bot: the scope discipline (AI-designed edge batches hunting derivation fault lines; identical injection both sides; self-cleaning batches that restore state; clone-only writes unless allow\_in\_place; run whatever ETL exists via the bot's own tools; always reply in the required JSON contract) travels in the MISSION PROMPT, not a bot persona, and the ACCESS the agent needs is provisioned PER MISSION (the mission names the exact source/target connection ids + clone endpoints, and the executor validates the bot can reach them before dispatch) rather than baked into a static loadout. Kept configurable so a dedicated least-privilege agent can be introduced later without a code change. Read at call time.

* **Type:** `string`
* **Default:** `"Eve"`
* **Override:** `GENESIS__ESTATE_CHAR__STIMULUS__AGENT_BOT_ID`

#### `estate_char.stimulus.agent_timeout_seconds`

Wall-clock ceiling for EACH agent turn of a commissioned stimulus executor (one design turn, one execute turn per round). On timeout the turn is abandoned and the run is stamped a terminal 'stalled' failure with the elapsed budget recorded, never left 'running' -- the run-lifecycle discipline (exactly one terminal write) holds, and this per-turn ceiling is also what bounds total cost when rounds > 1. Sized for a minutes-long agent turn (default 30 min); the legacy-bench executor ignores it (its programmatic path has its own per-statement guards). Read at call time.

* **Type:** `int`
* **Default:** `1800`
* **Override:** `GENESIS__ESTATE_CHAR__STIMULUS__AGENT_TIMEOUT_SECONDS`

#### `estate_char.stimulus.rounds`

How many DISTINCT synthetic datasets the agent designs + runs for one stimulus run. Default 1 keeps routine comparisons bounded; demos raise it to probe more fault lines. Rounds 2..n are SEPARATE follow-up calls on the SAME agent thread (never one mega-call, never fresh threads) so the agent reuses operational lessons from earlier rounds (e.g. how it figured out running the ETL) and avoids re-targeting what it already tested -- the server also passes a compact summary of prior rounds' targets + outcomes into each follow-up prompt so the no-retarget property holds even if the thread is compressed. Each round keeps the two-phase JSON contract, gets its own registered batch + step events (a GUI sub-step of the stimulus beat), and results aggregate into the run summary. A round-local failure (bad batch design) is recorded and the loop proceeds; an environmental failure (clone unreachable, ETL not runnable) stops the loop. Total cost is bounded by rounds x the per-turn agent\_timeout\_seconds. Clamped to >= 1 at call time. Read at call time.

* **Type:** `int`
* **Default:** `1`
* **Override:** `GENESIS__ESTATE_CHAR__STIMULUS__ROUNDS`

#### `estate_char.stimulus.bot_server_url`

URL of an ALREADY-RUNNING Genesis bot server the standalone stimulus bot driver points a proxy at, instead of booting an in-process server. Only the standalone acceptance-script driver consults it; a stimulus run commissioned through the backend never does (it is already inside the server). Empty (the default) means construct the embedded in-process proxy, which is the standalone-only path. Read at call time.

* **Type:** `string`
* **Default:** `""`
* **Override:** `GENESIS__ESTATE_CHAR__STIMULUS__BOT_SERVER_URL`

#### `estate_char.stimulus.require_clone`

Safety gate (default true): a stimulus run REFUSES to inject its batch into an estate that is not a throwaway clone/utility estate unless the run is submitted with allow\_in\_place=true. Injection mutates rows on both sides; the eval flows always operate on isolated clones, and a production (kind='normal') estate must never be mutated in place by accident. With this true and allow\_in\_place false, a run targeting a non-clone estate fails fast with a clear error before any write. Set false only to lift the clone requirement globally (not recommended); the per-run allow\_in\_place override is the sanctioned escape hatch. Batch rows are always self-cleaning regardless (the injected island is removed and scratch dropped in a finally). Read at call time.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__STIMULUS__REQUIRE_CLONE`

### estate\_char.preflight

#### `estate_char.preflight.enabled`

Master switch for estate preflight and its authed trigger (POST /api/estate/estates/\{estate\_id}/preflight). When true (default) the RATIFY-gated endpoint accepts a submit-and-poll preflight run against a named estate and records a real run row with per-check readiness lights + a thread-linked agent ETL check. When false the endpoint refuses (400) and no preflight (manual OR the post-save auto-preflight) is commissioned. Read at call time.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__PREFLIGHT__ENABLED`

#### `estate_char.preflight.auto_on_save`

Whether saving an estate (create OR edit) automatically fires a post-save preflight run in the background (non-blocking: the estate save returns immediately; the preflight reports into the live feed and the estate's readiness panel as its lights come on). Default true so setting an estate up feels like watching the green lights turn on. The agentic ETL check only commissions the agent when the estate has registered code\_assets -- an estate with no ETL fails that check immediately with no agent turn, so auto-preflight stays cheap for not-yet-complete estates. Set false to require an explicit 'Run preflight' click instead. Ignored when estate\_char.preflight.enabled is false. Read at call time.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__PREFLIGHT__AUTO_ON_SAVE`

#### `estate_char.preflight.etl_timeout_seconds`

Wall-clock ceiling for the agent's READ-ONLY ETL-understanding turn in the preflight ETL check. On timeout the turn is abandoned and the ETL light reports the timeout itself -- naming this budget and this setting -- rather than judging the partial reply's format, never left running -- the run-lifecycle discipline (exactly one terminal write) holds. Sized for a bounded read-and-explain turn (default 10 min), shorter than a full stimulus execute turn because this mission only LOCATES + READS the ETL, it never runs it. The agent bot is reused from estate\_char.stimulus.agent\_bot\_id (no separate preflight bot). Read at call time.

* **Type:** `int`
* **Default:** `600`
* **Override:** `GENESIS__ESTATE_CHAR__PREFLIGHT__ETL_TIMEOUT_SECONDS`

#### `estate_char.preflight.persist_clones`

Default for whether the CLONABILITY check leaves the Postgres scratch schema it provisions registered instead of tearing it down (Justin's 'make the clones right away' -- a per-run request may override this). Default false: the check does a real create-probe-then-DROP so it proves the clone privilege without leaving anything behind, and the check works identically whether or not clones persist. When true the scratch schema is kept and recorded on the check evidence. Note: the scratch schema is a lightweight clone-CAPABILITY probe, not the estate's full working clone (the eval path's CREATE DATABASE clone is provisioned at run time); persisting a full working clone is a follow-up. Read at call time.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__ESTATE_CHAR__PREFLIGHT__PERSIST_CLONES`

### estate\_char.live

#### `estate_char.live.enabled`

Master switch for the estate live-progress WebSocket channel (/api/ws/estate/live). When false the endpoint refuses connections (close 1013) and clients fall back to run-summary polling; the run workflows still write their durable summaries either way. Turn off only to force poll-only behavior.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__LIVE__ENABLED`

#### `estate_char.live.buffer_size`

Per-connection event mailbox depth (bounded asyncio queue). When a slow client cannot keep up, the oldest queued event is dropped and a lag counter is carried so the client re-snapshots rather than blocking the run loop or growing memory. Raise for very chatty scans on fast clients; lower to cap per-connection memory.

* **Type:** `int`
* **Default:** `256`
* **Override:** `GENESIS__ESTATE_CHAR__LIVE__BUFFER_SIZE`

#### `estate_char.live.heartbeat_seconds`

Idle heartbeat cadence: when no progress event arrives within this many seconds the server sends a `ping` frame to keep the socket and any intermediary proxies alive. Read at call time.

* **Type:** `int`
* **Default:** `20`
* **Override:** `GENESIS__ESTATE_CHAR__LIVE__HEARTBEAT_SECONDS`

#### `estate_char.live.store_tail_poll_seconds`

How often (seconds) the store-tailing pump re-reads a followed run's persisted summary to synthesize live events for a headless/API-launched run. This is what paces the theater's animation for runs the in-process hub never sees, so it wants to match the frontend's live cadence (5s) — NOT the socket keep-alive `heartbeat_seconds` (20s), which it previously borrowed and which made headless runs advance in visible 20-second jumps. One indexed run-row read per interval per followed run. Read at call time.

* **Type:** `int`
* **Default:** `5`
* **Override:** `GENESIS__ESTATE_CHAR__LIVE__STORE_TAIL_POLL_SECONDS`

#### `estate_char.live.idle_timeout_seconds`

Maximum time a live-theater socket may sit with no progress and no client message before the server closes it. Prevents abandoned tabs from holding connections indefinitely. Set high enough to outlast a long scan between phases.

* **Type:** `int`
* **Default:** `3600`
* **Override:** `GENESIS__ESTATE_CHAR__LIVE__IDLE_TIMEOUT_SECONDS`

#### `estate_char.live.object_stride`

Stream one `object_revealed` event every Nth object characterized during a scan (the final object is always emitted so the scan ring settles at done==total). Default 1 = every object (progressive reveal). Raise on estates with thousands of objects to thin the push stream; the persisted run summary always carries the exact running count regardless.

* **Type:** `int`
* **Default:** `1`
* **Override:** `GENESIS__ESTATE_CHAR__LIVE__OBJECT_STRIDE`

#### `estate_char.live.max_stream_elements`

Cap on the number of per-`element_verdict` deviation events streamed live for one system-diff run (the complete set always stays in the persisted mediated diff). Protects the socket from a pathological all-deviating diff. Set \<= 0 to stream every element.

* **Type:** `int`
* **Default:** `500`
* **Override:** `GENESIS__ESTATE_CHAR__LIVE__MAX_STREAM_ELEMENTS`

#### `estate_char.live.store_tail_enabled`

Master switch for the backend store-tailing pump that synthesizes live-theater events (phase / scan\_progress / object\_revealed / summary / done) from a followed run's persisted summary when its in-process live hub is silent — the store-first liveness path that makes headless/agent/API-launched runs watchable without the run executing inside the GUI-serving backend. When false the WS falls back to the one-shot snapshot + poll behavior for such runs. A backend-launched run whose hub is actively streaming is untouched either way (the pump stays dormant while hub events flow). Read at call time.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__LIVE__STORE_TAIL_ENABLED`

#### `estate_char.live.store_tail_grace_seconds`

For a backend-launched run, how many seconds the live WS may go with no in-process hub event before the store-tailing pump takes over and begins synthesizing events from the persisted summary (the connected-but-silent handover). A headless-script run bypasses this grace and is tailed from the store immediately, since its hub events can never reach this process. Raise if a healthy backend run can legitimately go quiet longer than the default between hub events; lower for a snappier handover. Read at call time.

* **Type:** `int`
* **Default:** `8`
* **Override:** `GENESIS__ESTATE_CHAR__LIVE__STORE_TAIL_GRACE_SECONDS`

#### `estate_char.live.recent_objects_buffer`

How many recent measured object names a running scan carries in its run summary (a bounded rolling buffer) so the store-tailing pump can synthesize object\_revealed events with REAL names for headless runs — with ZERO extra store writes, since the per-object summary write already happens (it is enriched, not added to). The exact running count is always carried separately; this only bounds how many names a poll-driven late-joiner can name per interval. Raise to name more objects per pump cycle at the cost of a larger summary payload. Read at call time.

* **Type:** `int`
* **Default:** `25`
* **Override:** `GENESIS__ESTATE_CHAR__LIVE__RECENT_OBJECTS_BUFFER`

#### `estate_char.live.outbox_enabled`

Master switch for the system-diff event outbox: a headless (non-backend) diff run buffers its mid-diff family\_found / element\_verdict events in memory and flushes them to the estate\_char\_run\_events table in batched multi-row INSERTs, and a single backend tail task per followed run republishes them into the live hub — so mid-diff verdict precipitation streams cross-process to the theater instead of appearing only at run end. ON by default for diff runs. A backend-launched diff needs no outbox (its emit() already reaches the hub in-process), so the outbox is written only by headless runs. When false, headless diffs show only the fold-at-completion the store-tailing pump derives from the run summary. Read at call time.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__LIVE__OUTBOX_ENABLED`

#### `estate_char.live.outbox_flush_events`

Flush the in-memory diff event outbox to the store once this many events have buffered (one batched multi-row INSERT). Bounds stream lag against write frequency: the run process NEVER blocks per event (it only appends to memory) and pays one INSERT per batch. Raise to trade a little more stream lag for fewer/larger writes on a chatty diff; lower for tighter latency at more writes. Read at call time.

* **Type:** `int`
* **Default:** `25`
* **Override:** `GENESIS__ESTATE_CHAR__LIVE__OUTBOX_FLUSH_EVENTS`

#### `estate_char.live.outbox_flush_seconds`

Flush the in-memory diff event outbox at least this often (seconds) even when fewer than outbox\_flush\_events have buffered, so a diff that emits slowly still streams within a bounded delay instead of waiting for the batch to fill. The flush is inline at the run's own event boundaries (no timer thread). Read at call time.

* **Type:** `int`
* **Default:** `2`
* **Override:** `GENESIS__ESTATE_CHAR__LIVE__OUTBOX_FLUSH_SECONDS`

#### `estate_char.live.outbox_tail_poll_seconds`

How often (seconds) the backend tail task polls the estate\_char\_run\_events outbox for a followed headless diff run (one indexed watermark read — WHERE run\_id=? AND seq>? ORDER BY seq — shared across every watcher of that run, not per-connection) and republishes new events into the live hub. Lower for snappier mid-diff streaming at more reads; raise to thin the poll. Read at call time.

* **Type:** `int`
* **Default:** `2`
* **Override:** `GENESIS__ESTATE_CHAR__LIVE__OUTBOX_TAIL_POLL_SECONDS`

### estate\_char.findings

#### `estate_char.findings.family_members_page_size`

Default and maximum number of finding rows returned in one page by the per-family members endpoint (GET /estate/system-diffs/\{diff\_hash}/families/\{family\_key}/members), the per-event drill-down (GET /estate/comparison-events/\{diff\_hash}/findings, view=rows), and the Human Review population endpoint (GET /estate/comparisons/\{diff\_hash}/review/population). A request without a limit returns this many; a larger limit is clamped to it. The client pages through with offset/limit to reach every row, so the full set always stays inspectable — this only bounds one response (protecting the server from a pathological 10k-member family), never what is reachable. Raise for very large families that should arrive in fewer round-trips.

* **Type:** `int`
* **Default:** `500`
* **Override:** `GENESIS__ESTATE_CHAR__FINDINGS__FAMILY_MEMBERS_PAGE_SIZE`

### estate\_char.dossier

#### `estate_char.dossier.max_members`

Safety ceiling on how many family members one family dossier pages in from the findings ledger. Every gathered member appears in the document's member table; if a family exceeds this, the table shows the first max\_members and the document points at the members API (GET /estate/system-diffs/\{diff\_hash}/families/\{family\_key}/members) for the remainder — so the full set stays reachable, never silently truncated. Raise for pathological alert-flood families that should be captured whole in one document.

* **Type:** `int`
* **Default:** `2000`
* **Override:** `GENESIS__ESTATE_CHAR__DOSSIER__MAX_MEMBERS`

#### `estate_char.dossier.max_evidence_members`

How many members get a full per-member evidence block (was→now values, detail, would-be-licensed-by, provenance) in a family dossier. Members beyond this still appear in the member table with their was→now summary; the document notes how many were not expanded and links the members API for their full evidence. Keeps a thousand-member family's document readable without hiding anything. Set \<= 0 to render the table only.

* **Type:** `int`
* **Default:** `50`
* **Override:** `GENESIS__ESTATE_CHAR__DOSSIER__MAX_EVIDENCE_MEMBERS`

#### `estate_char.dossier.max_sample_rows`

Cap on the number of concrete rows rendered per collection in a behavioral-divergence dossier — injected stimulus rows per case, and the source-only / target-only divergence samples per output. Beyond this the document shows the count and notes the full set is reachable via replay. Protects the document from a pathological large-case campaign. Raise to embed more of the actual data inline.

* **Type:** `int`
* **Default:** `25`
* **Override:** `GENESIS__ESTATE_CHAR__DOSSIER__MAX_SAMPLE_ROWS`

#### `estate_char.dossier.cache_enabled`

When true (default), the Issue Dossier modal persists each successful family-dossier assembly and serves later opens of the same family from that cache (instant, no ledger re-paging). A disposition/note write on a family drops its cached rows so the next open re-assembles with current adjudication state; ?refresh=true always bypasses and rewrites. Set false to always assemble the dossier live on every open (slow for large families) — e.g. while debugging the assembler itself.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__DOSSIER__CACHE_ENABLED`

#### `estate_char.dossier.pregenerate_enabled`

When true (default), a completed system-diff run pregenerates dossiers for its red/yellow clusters (every unlicensed/undecided finding family) in the background after the run's terminal event, and a one-boot backfill warms the most recent diffs' families — so the first 'Full details' click is instant instead of a \~27s live assembly. Never delays the run's done event and is non-fatal (a pregeneration failure only leaves a normal live-assemble-on-open). Set false to disable all dossier pregeneration (dossiers still cache read-through on first open).

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__DOSSIER__PREGENERATE_ENABLED`

#### `estate_char.dossier.pregenerate_max_families`

Upper bound on how many finding families one completed diff pregenerates dossiers for (largest families first — they are the costliest to assemble on click). A diff with more open families than this pregenerates only the top N; the rest still assemble-and-cache on first open. Keeps the post-run background warm bounded on a pathological many-family diff. Also bounds each diff in the one-boot backfill.

* **Type:** `int`
* **Default:** `40`
* **Override:** `GENESIS__ESTATE_CHAR__DOSSIER__PREGENERATE_MAX_FAMILIES`

#### `estate_char.dossier.pregenerate_backfill_diffs`

How many of the most recent (forward) mediated diffs the one-boot startup backfill pregenerates family dossiers for, so existing comparisons get instant 'Full details' after a restart without re-running them. Idempotent: families already cached are skipped. Set 0 to disable the startup backfill (post-run pregeneration and read-through caching still apply).

* **Type:** `int`
* **Default:** `10`
* **Override:** `GENESIS__ESTATE_CHAR__DOSSIER__PREGENERATE_BACKFILL_DIFFS`

### estate\_char.row\_samples

#### `estate_char.row_samples.cache_enabled`

When true (default), the witness data viewer persists each successful cross-engine sample fetch and serves later opens of the same finding from that cache (instant, zero estate queries). Set false to always run the live cross-engine probe on every drawer open (slow) — e.g. while debugging the probe itself.

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__ROW_SAMPLES__CACHE_ENABLED`

#### `estate_char.row_samples.ttl_hours`

How long a persisted witness sample stays fresh, in hours. Default 0 means NEVER expire: the sampled state is a frozen artifact of the compared snapshots, so a cached sample stays valid until an operator explicitly refreshes it (?refresh=true bypasses and rewrites the cache). Set > 0 to auto-expire cached samples after that many hours (the live tables can drift; a positive TTL re-fetches periodically without a manual refresh).

* **Type:** `int`
* **Default:** `0`
* **Override:** `GENESIS__ESTATE_CHAR__ROW_SAMPLES__TTL_HOURS`

### estate\_char.knowledge\_dossier

#### `estate_char.knowledge_dossier.enabled`

When true (default), a completed system-diff run captures each unlicensed/indeterminate finding family into the knowledge store (estate\_char\_knowledge\_dossiers) as a dual-view dossier (estate + redacted), deduping across estates by the pair-independent cross-family signature. Runs in the diff's post-terminal background step, bounded and wholly best-effort (a capture failure never affects the run). Set false to stop accruing the cross-customer knowledge base (e.g. for a runner that must not retain difference patterns at all).

* **Type:** `bool`
* **Default:** `true`
* **Override:** `GENESIS__ESTATE_CHAR__KNOWLEDGE_DOSSIER__ENABLED`

#### `estate_char.knowledge_dossier.capture_max_families`

Upper bound on how many finding families one completed diff captures into the knowledge store (largest families first — the systemic clusters carry the most signal). A diff with more unlicensed/indeterminate families than this captures only the top N; the rest are picked up when the pattern recurs on a later diff. Keeps the post-run capture bounded on a pathological many-family diff. Set \<= 0 to disable capture without turning the feature off entirely.

* **Type:** `int`
* **Default:** `40`
* **Override:** `GENESIS__ESTATE_CHAR__KNOWLEDGE_DOSSIER__CAPTURE_MAX_FAMILIES`

### estate\_char.store

#### `estate_char.store.snowflake_hybrid_tables`

On a Snowflake metadata database, create the five estatechar tables a disposition-package approval reads and writes by key (review events, correspondence rules and their bindings, rule field events, diff findings) as Snowflake hybrid tables. Measured on env3 on scratch copies: in 16 interleaved runs of the same 11-item approval, a keyed write took 0.31 s instead of 0.61 s (median), and once the hybrid tables had served a few approvals these tables' statements in one approval took 18.2 s instead of 23.4 s; on freshly loaded hybrid tables there was no difference. The findings table's own write paths were faster too: the startup family-signature backfill of 2,000 rows took 16.8 s instead of 25.4 s, and a comparison minting 200 findings took 196 s instead of 318 s. Only a bulk INSERT ... SELECT, as in a conversion, is slower (about 18x). Read when the store is first used after a start, by the process that first opens it; a process whose configuration is not yet initialized reads this as off, so on a fresh install whichever process opens the store first decides. It creates missing tables only: an existing standard table is never converted while Genesis runs; it is named in a warning, and the operator converts it with Genesis stopped by running scripts/convert\_estatechar\_tables\_to\_hybrid.py --genesis-is-stopped, which keeps each original as \<table>*standard*\<timestamp> and refuses to convert anything while a table holds two rows under one primary key (a hybrid table enforces its key; a standard one does not). Hybrid tables are created without CHECK constraints and with their two unique indexes as plain ones, because Snowflake cannot alter a CHECK on a hybrid table and a hybrid UNIQUE refuses a second NULL; the store writes those statuses from its own constants, and a standard Snowflake table enforces neither today. Hybrid tables are billed differently from standard ones (hybrid table storage and request charges). Off (default): standard tables, as before. Turning it off later does not convert back.

* **Type:** `bool`
* **Default:** `false`
* **Override:** `GENESIS__ESTATE_CHAR__STORE__SNOWFLAKE_HYBRID_TABLES`

## Measurement

#### `measurement.statement_timeout_ms`

Milliseconds one measurement statement may run while holding the source's REPEATABLE READ snapshot. A held snapshot pins the xmin horizon for as long as it lives, so an unbounded statement is sustained bloat pressure on the estate being measured. Postgres only -- it is issued as SET statement\_timeout on the held session and protects nothing on an engine without one. Clamped in code to 1800000 (30 minutes); larger values are reduced to the ceiling and the reduction is reported in the measurement run.

* **Type:** `int`
* **Default:** `300000`
* **Override:** `GENESIS__MEASUREMENT__STATEMENT_TIMEOUT_MS`

#### `measurement.pass_budget_seconds`

Wall-clock ceiling for one whole measurement pass, checked between statements. This is the session-independent bound, and it bounds how long a pass keeps ASKING -- not how long any one answer may take. It does NOT interrupt a statement already in flight -- per-statement bounding belongs to statement\_timeout\_ms and to each transport's own deadline. A single run may ask for less via the tool's budget\_seconds parameter; it may never ask for more. Clamped in code to 21600 (6 hours); larger values are reduced to the ceiling and the reduction is reported in the measurement run.

* **Type:** `int`
* **Default:** `3600`
* **Override:** `GENESIS__MEASUREMENT__PASS_BUDGET_SECONDS`

## Talend

#### `talend.project_path`

Filesystem path to the local Talend Open Studio project directory (holds talend.project and process/\*.item). Used to list and describe jobs by parsing their .item files. Example: /Users/me/talend/workspace/MY\_PROJECT

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__TALEND__PROJECT_PATH`
* **Environment default:** `TALEND_PROJECT_PATH`

#### `talend.jobs_dir`

Filesystem path to the directory of BUILT standalone Talend job artifacts (each an unzipped 'Build Job' export containing \<job>\_run.sh). Used to execute jobs. Example: /opt/talend/jobs

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__TALEND__JOBS_DIR`
* **Environment default:** `TALEND_JOBS_DIR`

#### `talend.runner_url`

Base URL of a remote 'talend-runner' HTTP service (e.g. [http://10.0.0.5:8899](http://10.0.0.5:8899)) that lists and executes built Talend jobs on another host. When set, list/run/get-run go over HTTP to this runner instead of the local filesystem; when empty, jobs run as a local subprocess from talend.jobs\_dir. Leave empty for local execution.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__TALEND__RUNNER_URL`
* **Environment default:** `TALEND_RUNNER_URL`

#### `talend.run_timeout_seconds`

Maximum seconds a built Talend job may run before the runner terminates it. Guards against a hung job holding a worker thread.

* **Type:** `int`
* **Default:** `900`
* **Override:** `GENESIS__TALEND__RUN_TIMEOUT_SECONDS`

#### `talend.cloud_base_url`

Talend Management Console (Talend Cloud) API base URL for your region, e.g. [https://api.eu.cloud.talend.com](https://api.eu.cloud.talend.com). Only used by the Talend Cloud surface (phase 2); ignored for local built-artifact execution.

* **Type:** `str`
* **Default:** `"https://api.us.cloud.talend.com"`
* **Override:** `GENESIS__TALEND__CLOUD_BASE_URL`
* **Environment default:** `TALEND_CLOUD_BASE_URL`

#### `talend.cloud_token`

Talend Cloud personal access token (secret reference/value). Only used by the Talend Cloud surface; local built-artifact execution needs no credentials.

* **Type:** `str`
* **Default:** `""`
* **Override:** `GENESIS__TALEND__CLOUD_TOKEN`
* **Startup environment variable:** `TALEND_CLOUD_TOKEN`
* **Secret**
