/** * Brain coordination primitives. * * Brain is an authority layer above a leader/director but below the human. It is * intentionally modeled as a decision interface first, not as an autonomous * bypass: callers ask for a decision, Brain either answers within policy or * escalates to the human. */ import type { EventBus } from '../kernel/events.js'; import { type BrainHeuristicsConfig } from './brain-heuristics.js'; export type BrainDecisionSource = 'goal' | 'director' | 'tool' | 'user' | 'system'; export type BrainRisk = 'low' | 'medium' | 'high' | 'critical'; /** * Canonical ordering of request risk, lowest first. The single source of * truth for every risk comparison in the Brain (tier ceilings, council * floors, rule `minRisk`/`maxRisk` bounds) — keeping it here, next to the * type it orders, stops the ladders from drifting apart. * * Typed as `Record` on purpose: callers index it with values * that arrive from config/JSON and may not be valid `BrainRisk` members, and * are expected to supply their own `?? default` for that case. */ export declare const BRAIN_RISK_LEVELS: Record; export type BrainFallback = 'ask_human' | 'deny' | 'continue'; export interface BrainDecisionOption { id: string; label: string; consequence?: string | undefined; risk?: BrainRisk | undefined; recommended?: boolean | undefined; } export interface BrainDecisionRequest { id: string; /** Active host session id for surfaces that multiplex multiple sessions. */ sessionId?: string | undefined; source: BrainDecisionSource; question: string; context?: string | undefined; options?: BrainDecisionOption[] | undefined; risk: BrainRisk; /** What a non-LLM/default Brain should do when policy cannot decide safely. */ fallback: BrainFallback; } export type BrainDecision = { type: 'answer'; optionId?: string | undefined; text: string; rationale?: string | undefined; } | { type: 'ask_human'; prompt: string; options?: BrainDecisionOption[] | undefined; rationale?: string | undefined; } | { type: 'deny'; reason: string; }; export interface BrainArbiter { decide(request: BrainDecisionRequest): Promise; } /** * Event-emitting decorator for any Brain implementation. Hosts wire this around * their actual arbiter so TUI/session surfaces can render Brain decisions * without coupling to the caller that requested the decision. */ export declare class ObservableBrainArbiter implements BrainArbiter { private readonly inner; private readonly events; constructor(inner: BrainArbiter, events: EventBus); decide(request: BrainDecisionRequest): Promise; } interface BrainDecisionQueueOptions { /** Safety fallback if the human never answers. Default: no timeout. */ timeoutMs?: number | undefined; /** * Decision to resolve with when the timeout fires. Default: deny. * Headless-leaning hosts pass `terminalPolicyDecision` here so an * unanswered prompt degrades to the safe default instead of a bare deny. */ onTimeout?: ((request: BrainDecisionRequest) => BrainDecision) | undefined; } /** * Bridge between an `ask_human` Brain decision and the UI. It emits the visible * ask-human event, then resolves when the TUI emits `brain.human_answered`. */ export declare class BrainDecisionQueue { private readonly events; private readonly opts; private readonly pending; private readonly offAnswer; constructor(events: EventBus, opts?: BrainDecisionQueueOptions); requestHumanDecision(request: BrainDecisionRequest): Promise; dispose(): void; } /** Escalation routing for the outermost Brain tier. See `EscalationRoutingBrainArbiter`. */ export type BrainEscalationMode = 'interactive' | 'headless'; /** * Resolve an `ask_human` escalation WITHOUT a human — the terminal policy of * a headless Brain. The ladder is deliberately conservative: * * 1. A caller-recommended option at low/medium request risk is chosen — * the caller already declared it the safe default. * 2. `fallback: 'continue'` requests continue (the caller stated that * continuing is the safe default when nobody can decide). * 3. Everything else is denied. Denial is always safe by contract: every * Brain call site treats deny as "do not take the proposed action". * * The rationale names the terminal policy so decision logs/ledgers make the * degradation visible instead of silent. */ export type BrainTerminalPolicy = 'conservative' | 'deny-all' | 'continue-on-recommended'; export declare function terminalPolicyDecision(request: BrainDecisionRequest, policy?: BrainTerminalPolicy): BrainDecision; /** * Outermost escalation tier that never lets an `ask_human` decision leak to * the caller. Routing is read PER DECISION so `/brain mode` switches apply * live: * * - 'interactive' (and a queue is wired) → prompt the human via the * `BrainDecisionQueue`, exactly like `HumanEscalatingBrainArbiter`. * - 'headless' (or no queue) → resolve through `terminalPolicyDecision`. * * This is the layer that makes a fully unattended Brain possible: with mode * 'headless' every decision terminates in answer/deny, never in a blocking * prompt. */ export declare class EscalationRoutingBrainArbiter implements BrainArbiter { private readonly inner; private readonly queue; private readonly getMode; /** Live terminal-policy variant, read per decision. Default 'conservative'. */ private readonly getTerminalPolicy?; constructor(inner: BrainArbiter, queue: BrainDecisionQueue | undefined, getMode: () => BrainEscalationMode, /** Live terminal-policy variant, read per decision. Default 'conservative'. */ getTerminalPolicy?: (() => BrainTerminalPolicy) | undefined); decide(request: BrainDecisionRequest): Promise; } /** * Decorator that turns `ask_human` into an actual awaited human decision. * The wrapped Brain remains policy-only; this layer owns the UI/event bridge. */ export declare class HumanEscalatingBrainArbiter implements BrainArbiter { private readonly inner; private readonly queue; constructor(inner: BrainArbiter, queue: BrainDecisionQueue); decide(request: BrainDecisionRequest): Promise; } export interface DefaultBrainArbiterOptions { /** * Allow deterministic auto-answering for low-risk requests. Default true. * @deprecated Prefer `heuristics.lowRiskAutoAnswer`; this still wins when set. */ allowLowRiskAutoAnswer?: boolean | undefined; /** Per-heuristic toggles. Omitted fields default to enabled. */ heuristics?: BrainHeuristicsConfig | undefined; } /** * Conservative deterministic Brain implementation. * * It only auto-answers low-risk requests when the caller provided a recommended * option. Everything else follows the request fallback. This gives hosts a safe * policy object to wire before an LLM-backed Brain exists. */ export declare class DefaultBrainArbiter implements BrainArbiter { private readonly heuristics; constructor(opts?: DefaultBrainArbiterOptions); decide(request: BrainDecisionRequest): Promise; } export declare function formatHumanPrompt(request: BrainDecisionRequest): string; export {}; //# sourceMappingURL=brain.d.ts.map