/** * Brain decision provenance — WHICH tier actually resolved a decision. * * The Brain chain is a ladder (rules → policy → cache → council → LLM → * escalation), but every tier returns a bare `BrainDecision` with no marker * saying where it came from. `ObservableBrainArbiter` sits OUTSIDE the chain, * so the events it emits — the only thing the TUI/WebUI/HQ surfaces see — * could not distinguish a free deterministic answer from one that cost a * multi-model council call. That made the single most important operational * question ("how often does the Brain actually burn an LLM?") unanswerable. * * Provenance is recorded OUT OF BAND, keyed by the identity of the * `BrainDecisionRequest` object, rather than as a field on `BrainDecision`: * * - `BrainDecision` is a public union compared structurally in a great many * places (`expect(d).toEqual(deny('…'))` throughout the Brain tests, and * equality checks in host code). Adding even an optional field would * change those comparisons. * - The SAME request object reference is threaded unchanged through every * tier, so its identity is already a reliable per-decision key. * - A `WeakMap` keeps this leak-free: when the request is collected, so is * its provenance entry. No cleanup protocol, no unbounded growth. * * Marks are last-writer-wins. Each tier marks itself as it RESOLVES; a tier * that defers to the next one must not mark. * * @module brain-telemetry */ import type { BrainDecisionRequest } from './brain.js'; /** * The tier that produced a decision, cheapest first. * * - `rule` — a configured deterministic `BrainRule` matched. * - `policy` — `DefaultBrainArbiter` fallback semantics. * - `heuristic` — a built-in pattern heuristic (quickDecide / blocked-resolved). * - `cache` — a previous identical decision was replayed. * - `ledger-guard`— denied deterministically from observed failure history. * - `council` — the multi-LLM panel decided. * - `llm` — the single-LLM tier decided. * - `terminal` — headless terminal policy (no human available). * - `human` — a person answered the escalation prompt. */ export type BrainDecisionTier = 'rule' | 'policy' | 'heuristic' | 'cache' | 'ledger-guard' | 'council' | 'llm' | 'terminal' | 'human'; /** Tiers that did NOT cost a provider call. */ export declare const DETERMINISTIC_BRAIN_TIERS: ReadonlySet; /** * Record which tier resolved this request. Call it at the point of RESOLUTION * — a tier that falls through to the next one must not mark, or the ladder's * provenance collapses onto whichever tier ran last. */ export declare function markDecisionTier(request: BrainDecisionRequest, tier: BrainDecisionTier): void; /** The tier that resolved this request, when a tier recorded itself. */ export declare function readDecisionTier(request: BrainDecisionRequest): BrainDecisionTier | undefined; /** True when the decision was reached without any provider call. */ export declare function isDeterministicTier(tier: BrainDecisionTier | undefined): boolean; /** Running per-tier tally, for `/brain stats` and the settings surfaces. */ export interface BrainTierStats { /** Decisions resolved by each tier. Tiers with no decisions are omitted. */ byTier: Partial>; /** Total decisions counted (including ones with no recorded tier). */ total: number; /** Decisions reached without any provider call. */ deterministic: number; /** Decisions that cost at least one provider call (`council` + `llm`). */ llmBacked: number; /** Decisions whose tier was never recorded. */ unattributed: number; } /** * Mutable per-tier counter. Hosts keep one per session and feed it from the * `brain.decision_*` event stream. */ export declare class BrainTierCounter { private readonly counts; private total; private unattributed; /** Count one decision. `undefined` counts toward `unattributed`. */ record(tier: BrainDecisionTier | undefined): void; snapshot(): BrainTierStats; reset(): void; } //# sourceMappingURL=brain-telemetry.d.ts.map