Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Libra Governor — Architecture

System shape

Claude Code -> deterministic hooks/statusline -> local Governor daemon -> optional enforcement gateway -> LLM provider

Libra is a local data plane: the component that actually decides whether work is admitted, tracks spend against an estimate, and gates replans lives on the developer’s machine, backed by SQLite in WAL mode.

Component responsibilities

Daemon (crates/daemon)

The daemon is the source of truth. It owns:

  • The admission state machine — a task is admitted only after the estimator has produced a probabilistic cost/time estimate and the policy has confirmed enough budget is reserved to finish it.
  • The ledger — an append-only, auditable record of estimated vs. actual spend per task, per replan.
  • Policy evaluation — quality floors, cost elasticity rules, and the criteria for what counts as a “material boundary crossing” that must interrupt the user versus a routine replan that proceeds automatically.

Nothing about admission, ledger integrity, or policy evaluation is delegated elsewhere. Every other component either feeds the daemon information or asks it a question; only the daemon decides.

Hooks (integrations/claude-code)

Deterministic lifecycle hooks wired into the host agent tool (Claude Code today; Codex and others are integration targets, not architectural exceptions). Hooks fire at admission time, at tool-use time, and at replan time, and call into the daemon synchronously. Hooks contain no policy logic of their own — they are thin, deterministic adapters between the host tool’s lifecycle events and the daemon’s API.

Enforcement gateway (crates/gateway, optional)

Where LLM provider traffic can be routed through an HTTP boundary, the gateway is the hard enforcement point for provider spend: it can refuse to forward a request that would violate a budget the daemon has already decided must not be exceeded. The gateway enforces; it does not decide. It exists only for the subset of deployments where routing traffic through it is possible and desired — it is not a requirement for Libra to function, and it is not a general-purpose LLM router.

Implemented in HORO-1144 as a library crate run on a thread inside the daemon process, gated at runtime by DaemonConfig.gateway: Option<..> (default None). “It does not decide” is structural rather than conventional: crates/gateway depends on libra-governor-domain and nothing else of Libra’s, so it cannot open the ledger or construct a Policy. Everything it is permitted to do to a task budget goes through the SpendAuthority trait it defines, whose only implementation lives in crates/daemon.

Not every deployment gets the same guarantee, and the system says so in types rather than in prose: EnforcementTier distinguishes a Governor-held API/BYOK credential (monetary hard cap enforced against a pinned pricing version) from a forwarded subscription credential (token usage observed exactly, no monetary cap — the provider does not expose that quota’s accounting) from no gateway at all. Configuration validation refuses to start a combination that would overclaim. See docs/adr/0003-gateway-enforcement-boundary.md.

MCP surface

The MCP interface is an explain/query/manual-control API only. It lets a user or another tool ask the daemon “why was this admitted,” “what is the current ledger state,” or issue a manual override command. MCP is never a security or enforcement boundary — anything reachable only through MCP is, by definition, not something the system depends on for correctness or safety. Enforcement lives in the daemon and (optionally) the gateway.

Skills / commands

Skills and slash-commands are UX only — convenience wrappers that call the daemon or MCP surface. They carry no independent state and no policy logic.

Statusline / system messages

The statusline and any system messages surfaced into the host agent tool are the visible explanation channel for execution and replan decisions. When the daemon admits, throttles, or replans work, that decision is made legible to the user through this channel — not buried in logs the user never sees.

Privacy boundary

Full prompt content, source code, and tool output remain local by default. The daemon’s ledger and state store data on-disk via SQLite; nothing about a task’s actual content is transmitted off the developer’s machine as part of Libra’s own operation. Only the optional gateway, when enabled and only for the traffic explicitly routed through it, touches data leaving the machine — and even then, it enforces provider-spend limits rather than inspecting or exfiltrating content for Libra’s own purposes. That is a structural guarantee too: the gateway’s gateway_requests provenance table has no column for a body, a header, a prompt, or tool output, and there is deliberately no debug body-dump logging switch at any level. Any future feature that would change this default requires an explicit, separately reviewed decision — it is not the default posture.

Local data plane

  • Language: Rust (workspace: crates/domain, crates/protocol, crates/daemon, crates/cli, crates/ledger, crates/estimator, crates/gateway).
  • Storage: SQLite, WAL mode, on the local filesystem.
  • Process model: a single long-lived local daemon process, a CLI (libra-governor) for direct interaction, and thin integration hooks for host agent tools.

This bootstrap ticket (HORO-1118) establishes the workspace skeleton and these documented boundaries only. Real domain logic, ledger schema, and estimator implementation are follow-up tickets (e.g. HORO-1124).