/** * Brain panel data model — pure types + row derivation shared by the * reducer (cursor clamping), the key hook (action dispatch), and the * component (render). Mirrors the auth-panel pattern: the TUI never * touches config files — every mutation goes through the host bridge, * which the CLI implements on top of its BrainRuntime (live apply + * persist to the global config). */ import type { BrainRiskLevel } from './brain-contracts.js'; /** One selectable Council decision lens, as published by the host. */ export interface BrainPanelPersona { id: string; name: string; description: string; /** Seats using this lens get veto power unless the seat overrides it. */ defaultVeto?: boolean | undefined; } /** One configured pool entry / council voter, display-mapped. */ export interface BrainPanelVoter { label: string; persona?: string | undefined; veto?: boolean | undefined; weight?: number | undefined; } /** Editable heuristic toggles, mirroring `BrainConfigSnapshot.heuristics`. */ export interface BrainPanelHeuristics { lowRiskAutoAnswer: boolean; blockedResolved: boolean; deadlockSkip: boolean; retryExhausted: boolean; continuePing: boolean; /** Custom resolution-marker word list (undefined = built-in list). Read-only here. */ blockedResolvedMarkers?: string[] | undefined; } /** Keys of the boolean heuristic toggles — the setter's `key` argument. */ export type BrainHeuristicKey = keyof Omit; export type BrainDenyIsTerminal = 'never' | 'when-decided' | 'always'; export type BrainTraceContent = 'none' | 'redacted' | 'full'; export type BrainTerminalPolicyValue = 'conservative' | 'deny-all' | 'continue-on-recommended'; /** Display-mapped snapshot of the live Brain settings. */ export interface BrainPanelSettings { mode: 'headless' | 'interactive'; riskLevel: BrainRiskLevel; strategy: 'fallback' | 'round-robin'; decisionTimeoutMs?: number | undefined; humanTimeoutMs?: number | undefined; /** Configured pool entries as compact "provider/model" labels. */ pool: string[]; /** Resolved pool labels from the last assembly (≤ pool.length). */ poolResolved: string[]; usingSessionModel: boolean; councilEnabled: boolean; councilMinRisk: 'medium' | 'high' | 'critical'; /** Fraction of seats that must return a valid vote (undefined = default 0.5). */ councilQuorum?: number | undefined; /** Fraction of cast weight the winner must exceed (undefined = default 0.5). */ councilApproval?: number | undefined; /** Panel-diversity warning policy. A same-model panel agrees with itself. */ councilDistinctness: 'none' | 'model' | 'provider'; /** Per-seat completion timeout (undefined = inherit the decision timeout). */ councilPerCallTimeoutMs?: number | undefined; /** Seats polled concurrently, 1..8 (undefined = default 3). */ councilMaxConcurrency?: number | undefined; /** Output budget per voter seat call (undefined = default 2000). */ councilVoterMaxTokens?: number | undefined; /** Output budget for the judge call (undefined = follows the seat budget). */ councilJudgeMaxTokens?: number | undefined; /** Explicitly configured voters (empty = seats derive from the pool). */ voters: BrainPanelVoter[]; /** * Selectable decision lenses, published by the host from the Council persona * registry. Absent on hosts that predate the catalog — `personaCycle()` then * falls back to the three lenses the panel used to hard-code. */ personaCatalog?: BrainPanelPersona[] | undefined; /** Effective council seat labels (empty = council disabled). */ councilSeats: string[]; /** * EFFECTIVE council judge (resolved, not merely configured). Undefined when * no council is wired. */ judgeLabel?: string | undefined; /** False when `judgeLabel` was derived from the pool rather than configured. */ judgeConfigured?: boolean | undefined; /** True when the effective judge is also a seated voter (correlated tie-break). */ judgeIsVoter?: boolean | undefined; ledgerEnabled: boolean; autoDenyAfterFailures?: number | undefined; /** Headless escalation variant. */ terminalPolicy: BrainTerminalPolicyValue; /** Effective heuristic toggles (defaults already filled in by the host). */ heuristics: BrainPanelHeuristics; /** Single-LLM tier quality gate. */ llmMaxTokens: number; llmRejectUncertain: boolean; llmMinConfidence: number; llmDenyIsTerminal: BrainDenyIsTerminal; /** Decision cache: effective settings + LIVE counters (counters read-only). */ cacheEnabled: boolean; cacheTtlMs: number; cacheMaxEntries: number; cacheHits: number; cacheMisses: number; cacheSize: number; /** Replay trace. `tracePath` is read-only (edited via config). */ traceEnabled: boolean; traceContent: BrainTraceContent; tracePath?: string | undefined; /** Live LLM circuit-breaker state; undefined = no breaker wired. READ-ONLY. */ circuitState?: string | undefined; circuitFailures?: number | undefined; /** Deterministic rule table summary. READ-ONLY. */ ruleCount: number; /** Compile diagnostics from the last assembly, one per dropped rule. READ-ONLY. */ ruleErrors: string[]; } /** * Host bridge implemented by the CLI. Every setter returns an error string * (shown as the panel hint) or null on success; all setters apply LIVE and * persist to the active profile config. Model SELECTION is not part of this * bridge — the panel uses the shared /model picker via requestModelPick. */ export interface BrainPanelHost { getSettings(): BrainPanelSettings; setMode(mode: 'headless' | 'interactive'): Promise; setRisk(level: BrainRiskLevel): Promise; setStrategy(strategy: 'fallback' | 'round-robin'): Promise; setDecisionTimeout(ms: number | undefined): Promise; setHumanTimeout(ms: number | undefined): Promise; addPoolModel(providerId: string, model: string): Promise; removePoolModel(index: number): Promise; clearPool(): Promise; setCouncilEnabled(on: boolean): Promise; setCouncilMinRisk(risk: 'medium' | 'high' | 'critical'): Promise; addVoter(providerId: string, model: string): Promise; removeVoter(index: number): Promise; cycleVoterPersona(index: number): Promise; toggleVoterVeto(index: number): Promise; setJudge(providerId: string, model: string): Promise; clearJudge(): Promise; setCouncilQuorum(fraction: number): Promise; setCouncilApproval(fraction: number): Promise; setCouncilDistinctness(mode: 'none' | 'model' | 'provider'): Promise; /** * The positive-integer council knobs. `undefined` clears back to the * default — unlike the LLM/cache ladders, `BrainCouncilPatch` accepts `null` * for these, so a "default" rung is reachable here. */ setCouncilPerCallTimeout(ms: number | undefined): Promise; setCouncilMaxConcurrency(count: number | undefined): Promise; setCouncilVoterMaxTokens(tokens: number | undefined): Promise; setCouncilJudgeMaxTokens(tokens: number | undefined): Promise; setLedgerEnabled(on: boolean): Promise; setAutoDeny(count: number | undefined): Promise; setTerminalPolicy(policy: BrainTerminalPolicyValue): Promise; setHeuristic(key: BrainHeuristicKey, on: boolean): Promise; /** * NOTE the numeric LLM/cache knobs take a plain number: the underlying * `BrainConfigPatch` validators reject `null` for these fields ("must be a * positive integer"), so there is no "clear back to default" step here — * the preset ladders are number-only. */ setLlmMaxTokens(tokens: number): Promise; setLlmRejectUncertain(on: boolean): Promise; setLlmMinConfidence(value: number): Promise; setLlmDenyIsTerminal(mode: BrainDenyIsTerminal): Promise; setCacheEnabled(on: boolean): Promise; setCacheTtl(ms: number): Promise; setCacheMaxEntries(count: number): Promise; setTraceEnabled(on: boolean): Promise; setTraceContent(content: BrainTraceContent): Promise; } /** One selectable row of the settings view. */ export type BrainPanelRow = { kind: 'mode'; } | { kind: 'risk'; } | { kind: 'strategy'; } | { kind: 'timeout'; } | { kind: 'humanTimeout'; } | { kind: 'poolModel'; index: number; } | { kind: 'poolAdd'; } | { kind: 'councilToggle'; } | { kind: 'councilMinRisk'; } | { kind: 'voter'; index: number; } | { kind: 'voterAdd'; } | { kind: 'judge'; } | { kind: 'councilQuorum'; } | { kind: 'councilApproval'; } | { kind: 'councilDistinctness'; } | { kind: 'councilTimeout'; } | { kind: 'councilConcurrency'; } | { kind: 'councilVoterMaxTokens'; } | { kind: 'councilJudgeMaxTokens'; } | { kind: 'ledgerToggle'; } | { kind: 'autoDeny'; } | { kind: 'terminalPolicy'; } | { kind: 'heuristic'; key: BrainHeuristicKey; } | { kind: 'llmMaxTokens'; } | { kind: 'llmRejectUncertain'; } | { kind: 'llmMinConfidence'; } | { kind: 'llmDenyIsTerminal'; } | { kind: 'cacheToggle'; } | { kind: 'cacheTtl'; } | { kind: 'cacheMaxEntries'; } | { kind: 'traceToggle'; } | { kind: 'traceContent'; } | { kind: 'cacheStats'; } | { kind: 'tracePath'; } | { kind: 'circuit'; } | { kind: 'rulesSummary'; } | { kind: 'ruleErrors'; }; /** * Rows that only REPORT live/derived state. They are rendered dim and are * skipped by the adjust/enter handlers — there is nothing to write back. */ export declare const BRAIN_READONLY_ROW_KINDS: ReadonlySet; /** Heuristic rows, in display order. */ export declare const BRAIN_HEURISTIC_KEYS: readonly BrainHeuristicKey[]; /** * Derive the selectable rows for a settings snapshot. * * Array/optional reads are defensive: this is a pure display function driven * by whatever the host last pushed over `brainSettingsLoaded`, and a host that * predates a field (or an older persisted payload) must render fewer rows, not * crash the whole TUI. */ export declare function brainPanelRows(settings: BrainPanelSettings): BrainPanelRow[]; /** Preset ladders for ←/→ cycling on numeric rows. */ export declare const DECISION_TIMEOUT_PRESETS: ReadonlyArray; export declare const HUMAN_TIMEOUT_PRESETS: ReadonlyArray; export declare const AUTO_DENY_PRESETS: ReadonlyArray; /** * Number-only ladders. The Brain patch validators reject `null` for these * fields, so there is no `undefined` ("back to default") rung — the default * value itself is the first rung. */ export declare const LLM_MAX_TOKENS_PRESETS: readonly number[]; export declare const LLM_MIN_CONFIDENCE_PRESETS: readonly number[]; export declare const CACHE_TTL_PRESETS: readonly number[]; export declare const CACHE_MAX_ENTRIES_PRESETS: readonly number[]; /** * Council ladders. `undefined` is the "default" rung — `BrainCouncilPatch` * accepts `null` for these three, unlike the LLM/cache knobs. */ export declare const COUNCIL_FRACTION_PRESETS: readonly number[]; export declare const COUNCIL_DISTINCTNESS_PRESETS: ReadonlyArray<'none' | 'model' | 'provider'>; export declare const COUNCIL_TIMEOUT_PRESETS: ReadonlyArray; export declare const COUNCIL_CONCURRENCY_PRESETS: ReadonlyArray; export declare const COUNCIL_JUDGE_MAX_TOKENS_PRESETS: ReadonlyArray; /** * Per-seat output budget rungs. The default is 2000 (see * `BRAIN_COUNCIL_DEFAULT_VOTER_MAX_TOKENS` in core) — reasoning models spend * their thinking tokens from this budget, so the rungs skew higher than the * judge ladder. */ export declare const COUNCIL_VOTER_MAX_TOKENS_PRESETS: ReadonlyArray; /** * Fallback lens cycle for hosts that publish no `personaCatalog`. Prefer * {@link personaCycle}, which uses the host's catalog when it is available — * the registry ships six lenses, not these three. */ export declare const PERSONA_CYCLE: readonly ['executor', 'skeptic', 'auditor']; /** Lens ids the panel may cycle through for the given settings snapshot. */ export declare function personaCycle(settings: BrainPanelSettings): readonly string[]; /** Human-readable lens name for a persona id, falling back to the id itself. */ export declare function personaLabel(settings: BrainPanelSettings, id: string | undefined): string; /** Cycle helper: step through a preset ladder from the current value. */ export declare function cyclePreset(presets: ReadonlyArray, current: T, delta: number): T; //# sourceMappingURL=brain-panel-model.d.ts.map