/** * @module koi/oo-harness/telemetry * * What the harness looks like from outside, while it is running. * * A long autonomous run is opaque by default: a spinner, then an hour, then a * paragraph. The whole reason the object-oriented harness is worth building is * that its internals are already the right things to WATCH — the workbench of * live variables, the cells as they execute, the addressable history, and how * much of the context each region is using. * * This turns those into one small frame, emitted on the same event channel the * rest of the koi already uses, so both surfaces render the same truth: the * terminal draws it as a panel, the website draws it in Koi at work. Frames * are small and idempotent — a dropped one costs nothing, because the next one * carries the whole current state. */ import type { CellSession } from "./cell-session.js"; import type { HarnessEventLog } from "./harness-events.js"; export type HarnessFrame = { /** Which run this is, so several can be watched at once. */ runId: string; at: number; /** Cells executed so far in this run. */ cells: number; /** Live workbench: name, preview, rough size. */ bindings: Array<{ name: string; preview: string; size: number; note?: string; }>; /** Total bytes-ish held live — the number that says "this is why it is fast". */ liveBytes: number; /** The tail of the addressable history. */ events: Array<{ tag: number; kind: string; title: string; at: number; }>; /** The three context regions, in characters. */ context?: { static: number; events: number; dynamic: number; total: number; }; /** Set once the run submits a validated result. */ finished?: { summary: string; verification: string; }; }; export type HarnessTelemetryOptions = { runId: string; session: CellSession; events: HarnessEventLog; /** Where a frame goes. Usually the koi's own event channel. */ emit: (frame: HarnessFrame) => void; /** Minimum gap between frames; bursts are coalesced. */ minIntervalMs?: number; contextSizes?: () => HarnessFrame["context"]; }; export declare class HarnessTelemetry { private readonly options; private lastEmit; private pending; private finished; constructor(options: HarnessTelemetryOptions); /** Build the current frame without sending it. */ frame(): HarnessFrame; /** * Send a frame, coalescing bursts. `force` is for the moments that must land * — the first frame, and the last one. */ push(force?: boolean): void; markFinished(summary: string, verification: string): void; stop(): void; } /** One line for a terminal status bar: the frame at a glance. */ export declare function renderFrameLine(frame: HarnessFrame): string;