Skip to content

config — top-level modules

config.loader

Load non-secret configuration into frozen, typed dataclasses.

Secrets are never stored here. get_secret is the single sanctioned access point for later phases, and reads the environment (Keychain-backed in the owner's setup) only.

REPO_ROOT = Path(__file__).resolve().parent.parent module-attribute

LEVERS_OVERLAY = Path(__file__).resolve().parent / 'levers.toml' module-attribute

OllamaConfig dataclass

host instance-attribute

port instance-attribute

default_keep_alive instance-attribute

request_timeout_s instance-attribute

generation_timeout_s instance-attribute

base_url property

ResourceConfig dataclass

usable_ram_gb instance-attribute

max_resident_models instance-attribute

PathsConfig dataclass

data_dir instance-attribute

telemetry_db instance-attribute

raw_store instance-attribute

vector_store instance-attribute

derived_store instance-attribute

vault_catalog instance-attribute

attestation_store instance-attribute

VaultConfig dataclass

path instance-attribute

pattern instance-attribute

watch_debounce_s = 1.0 class-attribute instance-attribute

watch_poll_interval_s = 5.0 class-attribute instance-attribute

EmbeddingConfig dataclass

model instance-attribute

dim instance-attribute

query_instruction instance-attribute

DreamingConfig dataclass

similarity_threshold instance-attribute

min_cluster_size instance-attribute

max_clusters instance-attribute

near_dup_threshold instance-attribute

DreamRnDConfig dataclass

Dream-phase R&D track (FEATURE-FLAG OFF by default). The interpreter panel + adjudicator refuse to run unless enabled is True — see core/dreaming/rnd.py.

enabled instance-attribute

sigma instance-attribute

min_degree instance-attribute

bridge_clustering_max instance-attribute

centrality_top_k instance-attribute

agreement_jaccard instance-attribute

bridge_top_k instance-attribute

hole_min_persistence instance-attribute

sbm_k_max instance-attribute

InterfaceConfig dataclass

handoff_dir instance-attribute

default_adapter instance-attribute

AmbassadorConfig dataclass

The conversational front door (Track B). Runs on the pinned tier (always warm); these are its judgment bounds, not behavior switches: retrieval_k caps per-turn retrieval depth (the budgeter enforces the window regardless), history_max_turns caps the cheap in-memory working context (older context is RE-retrieved from the authored-dialogue corpus, not double-stored), and interruption_sensitivity ∈ {off, earned_only, verbose} is the owner-tunable unprompted-message dial (default earned_only — note §3).

retrieval_k = 5 class-attribute instance-attribute

history_max_turns = 6 class-attribute instance-attribute

interruption_sensitivity = 'earned_only' class-attribute instance-attribute

MonitorConfig dataclass

The edge monitor — a small dashboard + chat surface over Tailscale (Zone B). A SEPARATE process palace supervises; it reads the core-emitted status snapshot and relays chat over the interface handoff, never importing core (Invariant 2). OFF by default; bind host to the Tailscale IP (not 0.0.0.0) so the tailnet is the auth boundary, same as the note-sync setup. status_path is where the launcher writes the metadata snapshot the dashboard renders.

enabled = False class-attribute instance-attribute

host = '127.0.0.1' class-attribute instance-attribute

port = 8787 class-attribute instance-attribute

status_path = Path('data/monitor/status.json') class-attribute instance-attribute

request_timeout_s = 30.0 class-attribute instance-attribute

EffectorsConfig dataclass

Track G effector surface (docs/design-notes/hands-and-the-effector-layer.md). Fail-closed twice over: enabled off refuses to build either side of the handoff, and an empty upstreams allowlist refuses every fetch even when enabled. upstreams is (name, url) pairs — the ONLY place a URL exists in the sensing path; the core-side request carries just the name.

Sensing (β = 0) is the only class the WIRED surface admits (EffectView ceiling ε = SENSING). The acting-class knobs below (ledger_db, drafts_dir, jit_credential_ttl) support the built-but-off reversible/irreversible hands (G5/G6): the durable effect ledger, where a reversible write stages its draft, and the short TTL of the per-action JIT credential minted at send time. They are inert until ε is deliberately raised past sensing.

enabled = False class-attribute instance-attribute

handoff_dir = Path('data/handoff/sensing') class-attribute instance-attribute

timeout_s = 20.0 class-attribute instance-attribute

max_response_kb = 512 class-attribute instance-attribute

upstreams = () class-attribute instance-attribute

ledger_db = Path('data/effectors/effects.sqlite') class-attribute instance-attribute

drafts_dir = Path('data/effectors/drafts') class-attribute instance-attribute

jit_credential_ttl = '60s' class-attribute instance-attribute

AirlockConfig dataclass

Research airlock (§16). The sealed core uses only handoff_dir; the rest is Zone-B bridge config (S3 target + the narrowly-scoped assumed role). The core never reads S3.

handoff_dir instance-attribute

s3_bucket instance-attribute

s3_region instance-attribute

aws_profile instance-attribute

requests_prefix instance-attribute

results_prefix instance-attribute

poll_interval_s instance-attribute

poll_timeout_s instance-attribute

AttestationConfig dataclass

Runtime proof layer (attestation-layer.md). Records are always written; enabled gates SIGNING. Pub-key paths are committed (non-secret); the private seeds live in Keychain/Vault.

enabled = False class-attribute instance-attribute

signing_key_secret = 'attestation-signing-key' class-attribute instance-attribute

owner_key_secret = 'attestation-owner-key' class-attribute instance-attribute

supervisor_pub = Path('ops/attestation/supervisor.pub') class-attribute instance-attribute

owner_pub = Path('ops/attestation/owner.pub') class-attribute instance-attribute

SecretsConfig dataclass

Vault as a per-interaction runtime authorization layer (vault-runtime-auth.md). enabled only gates whether build_secrets_backend wires a real VaultClient — get_secret(name) with no token is unaffected either way (env/Keychain, unchanged).

enabled = False class-attribute instance-attribute

addr = 'http://127.0.0.1:8200' class-attribute instance-attribute

kv_mount = 'kv' class-attribute instance-attribute

aws_mount = 'aws' class-attribute instance-attribute

grant_roles = frozenset() class-attribute instance-attribute

token_ttl = '10m' class-attribute instance-attribute

BackupConfig dataclass

restic → S3 encrypted backups (BUILD-SPEC §16b). restic encrypts + deduplicates CLIENT-SIDE, so AWS never sees plaintext; the bucket's SSE-KMS is defense in depth. enabled gates the scheduled job only. The repo password and the backup AWS key live in Keychain (named here, never stored here). Off by default — turn on per machine via config/local.toml once the bucket is applied and Keychain is placed.

enabled = False class-attribute instance-attribute

repository = '' class-attribute instance-attribute

password_secret = 'restic-password' class-attribute instance-attribute

aws_access_key_id_secret = 'backup-aws-access-key-id' class-attribute instance-attribute

aws_secret_access_key_secret = 'backup-aws-secret-access-key' class-attribute instance-attribute

region = 'us-east-1' class-attribute instance-attribute

vault_snapshot = True class-attribute instance-attribute

exclude = ('logs', 'queue.sqlite', 'queue.sqlite-wal', 'queue.sqlite-shm', '*-shm', '*.lock', '.DS_Store') class-attribute instance-attribute

keep_daily = 7 class-attribute instance-attribute

keep_weekly = 4 class-attribute instance-attribute

keep_monthly = 6 class-attribute instance-attribute

SelfModConfig dataclass

The self-modification loop (BUILD-SPEC §14, Phase 10). Two fail-closed switches: enabled is the master switch for the whole propose→approve→execute→validate→rollback loop; unattended_enabled separately gates the ONLY path that acts without human approval (the §14 'safe levers'). Both OFF by default — a fresh clone can't self-modify, and never unattended, until the owner deliberately turns each on in config/local.toml.

enabled = False class-attribute instance-attribute

unattended_enabled = False class-attribute instance-attribute

ledger_db = Path('data/selfmod_ledger.sqlite') class-attribute instance-attribute

SandboxConfig dataclass

runtime instance-attribute

image instance-attribute

timeout_s instance-attribute

memory instance-attribute

cpus instance-attribute

pids_limit instance-attribute

max_concurrency instance-attribute

warm_pool_size instance-attribute

wasm_module = '' class-attribute instance-attribute

ModelConfig dataclass

name instance-attribute

tier instance-attribute

pinned instance-attribute

resident_gb instance-attribute

num_ctx instance-attribute

evicts_pinned = False class-attribute instance-attribute

Config dataclass

ollama instance-attribute

resources instance-attribute

paths instance-attribute

vault instance-attribute

embedding instance-attribute

dreaming instance-attribute

dream_rnd instance-attribute

sandbox instance-attribute

interface instance-attribute

airlock instance-attribute

models instance-attribute

ambassador = field(default_factory=AmbassadorConfig) class-attribute instance-attribute

monitor = field(default_factory=MonitorConfig) class-attribute instance-attribute

attestation = field(default_factory=AttestationConfig) class-attribute instance-attribute

secrets = field(default_factory=SecretsConfig) class-attribute instance-attribute

backup = field(default_factory=BackupConfig) class-attribute instance-attribute

selfmod = field(default_factory=SelfModConfig) class-attribute instance-attribute

effectors = field(default_factory=EffectorsConfig) class-attribute instance-attribute

pinned_model property

model_for_tier(tier)

load_config(path=None)

get_config() cached

refresh_config()

Drop the cached Config and reload from disk. Called after the self-mod loop writes a knob to levers.toml (ops/apply.py) so the change actually takes effect for subsequent get_config() callers in a long-running process, rather than waiting on a restart.

get_secret(name, token=None)

Fetch a secret. With no token: environment (Keychain-backed in the owner's setup) — the owner-operated / bootstrap path, unchanged from Phase 0.

With a token: a Vault ephemeral token minted for the calling agent's role (Supervisor.mint_token, vault-runtime-auth.md §2). The agent receives the token in its context, passes it here, and never constructs or stores it; Vault enforces the role's policy and raises VaultPermissionDenied if the path is out of scope — the agent learns nothing beyond "denied". The import lazily inside this branch only: config.loader is imported throughout core/, and hvac must never become a transitive hard dependency of that import (mirrors the lazy boto3/watchdog pattern elsewhere in this repo).

Secrets are NEVER stored in config files or committed, and never passed to a model (Invariant 10).

config.secrets_backend

Vault as a per-interaction runtime authorization layer (design-notes/vault-runtime-auth.md).

The object-capability model already scopes store handles at the code level (the dreamer gets a MirrorView, never a raw vector store). This module closes the matching gap at the credential level: an agent never holds a real secret, only an ephemeral token minted by the supervisor and scoped to a named policy (role). A token that doesn't cover a path is denied — the agent learns nothing beyond "denied" (VaultPermissionDenied).

hvac (the Vault HTTP client) is real-Vault-only and lazily imported inside VaultClient, so importing this module — or config.loader, which imports it lazily too — never requires hvac to be installed. The import-firewall (ops/import_lint.py) additionally blocks hvac from ever appearing under core/: agents receive tokens in context (Phase 5), they never call Vault directly. This module lives in config/, one level below get_secret(), exactly like the design note's import-discipline section specifies.

Phase scope (Steps 4–5 of the security & attestation track, NOT a numbered phase): the primitives below (FakeVault, VaultClient, build_secrets_backend, and MintedToken) and the scope-enforcement tests that exercise them. Step 5 added the accessor half of MintedToken — a mint's non-secret audit handle, which an attestation records in vault_token_accessor to tie an action to its authorization (the Vault↔attestation join; never the token — see MintedToken). Threading minted tokens into the dreamer/curator/vault-sync call sites is explicitly deferred to Phase 5 (agent factory + dispatcher) per the design note's own framing — this module makes that wiring possible without itself performing it.

VaultPermissionDenied

Bases: Exception

Raised when a token is unknown, or known but its role's policy doesn't cover the path. Deliberately uninformative beyond that — the caller (an agent) must not learn why it was denied, only that it was; the Vault audit log (or FakeVault.denials in tests) is where the detail belongs (vault-runtime-auth.md §6 — denials are an alignment signal, not noise).

MintedToken dataclass

What a mint returns: the secret token AND its accessor — Vault hands back both in one response (resp["auth"]["client_token"] / ["accessor"]). The two live in different keyspaces and do different jobs (the Step-5 Vault↔attestation join, attestation-layer.md §2):

token — the credential. The agent uses it (get_secret(name, token=...)) and nothing else may. NEVER logged, attested, or shown to a model (Invariant 10). • accessor — a non-secret audit handle. It can look up a token's metadata or revoke it, but cannot authenticate or read any secret. THIS is what an attestation records in vault_token_accessor, tying an action to its Vault authorization without ever exposing the credential.

The supervisor holds the whole MintedToken: it passes .token to the agent (in context, Phase 5) and records .accessor in the attestation it emits for that action.

token instance-attribute

accessor instance-attribute

SecretsBackend

Bases: Protocol

What both FakeVault (tests) and VaultClient (real Vault) implement — the supervisor and get_secret(..., token=...) depend on this shape, never on which one is wired.

mint_token(role, ttl)

read_secret(name, token)

FakeVault dataclass

An in-memory dev/test double — no real Vault, no network, no subprocess. policies maps a role name to the exact set of secret names its tokens may read (the dev-mode analogue of an HCL policy's path stanzas, see ops/vault/policies/); secrets is the backing key-value store. Every mint and every read/deny is recorded for assertions.

policies instance-attribute

secrets = field(default_factory=dict) class-attribute instance-attribute

minted = field(default_factory=list) class-attribute instance-attribute

denials = field(default_factory=list) class-attribute instance-attribute

mint_token(role, ttl)

read_secret(name, token)

role_for_accessor(accessor)

The dev-mode analogue of Vault's lookup-accessor: resolve an accessor to the role it was minted for, WITHOUT the token. This is what makes the Step-5 join verifiable — an attestation's vault_token_accessor can be confirmed to match its claimed agent_role. Returns None for an unknown accessor (or for a token passed here — wrong keyspace).

VaultClient

Real Vault, via hvac. Construction is side-effect-free — no connection is opened until mint_token/read_secret is actually called — mirroring OllamaClient/lancedb.connect elsewhere: safe to build in a wiring test without a live Vault dev-server running.

supervisor_token is the supervisor's own bootstrap credential (the bottom turtle for this layer — placed in Keychain/env via get_secret("vault-supervisor-token"), same pattern as the attestation signing keys). It is used only to mint child tokens; reads always go through a freshly-scoped client built from the caller's token, never the supervisor's.

hvac is imported per-method, not in __init__: edge/bridge/bridge.py holds the same line for boto3 ("imported LAZILY... so tests with a fake client never require boto3 installed") — this is that pattern applied here, so a wiring test can construct and inspect a VaultClient (addr, kv_mount) with no Vault dev-server and no hvac installed; only an actual mint_token/read_secret call needs the real package.

addr = addr instance-attribute

kv_mount = kv_mount instance-attribute

mint_token(role, ttl)

read_secret(name, token)

build_secrets_backend(config=None)

Wire a real VaultClient from [secrets]None when disabled, the normal state until the owner stands up a Vault dev-server (Step 6 runbook). Unlike attestation's fail-closed signing gate, a missing supervisor token here is not a silent-fallback risk (there is no insecure fallback path to slip into) — it simply surfaces as an hvac auth error on the first real mint_token call, not at construction.