import type { TraceAttachment, TraceSink } from "../../core/ports.js"; import type { TraceEvent } from "../../core/trace.js"; export declare class JsonlTraceSink implements TraceSink { #private; private readonly resolvePath; /** * Every event this sink saw, in order — so a host can project the run without re-reading the * file it just wrote. Retained for the whole run: a trace is small per event, but a long suite * holds them all, and a host that does not need them can read the file instead. */ readonly events: TraceEvent[]; /** * The path is resolved from the header's own `runId` rather than supplied up front, so the run * has exactly one identity — the engine's — instead of a file name and a header disagreeing. * `startTrace` emits the header synchronously, so `runId`/`path` are set before it returns. */ constructor(resolvePath: (runId: string) => string); get runId(): string | undefined; get path(): string | undefined; /** * Where this run's attachment bytes land: the trace file's own name, without its extension — * `runs/.jsonl` → `runs//`. A reader resolves `attachment: "12"` by looking for * `12.*` in there and nothing else: no manifest, no index, so a run that ends mid-write still * leaves every already-written attachment readable (spec/core/trace.md §Attachments). */ get attachmentsDir(): string | undefined; /** Writes that failed. Surfaced rather than hidden: a truncated trace must not read as a clean one. */ get failures(): number; emit(event: TraceEvent): void; /** * Bytes for an attachment the next `step` event references by id. Same contract as `emit`: * buffer, swallow, count — implementing this method is what makes the engine capture * screenshots for the trace at all. */ attach(attachment: TraceAttachment): void; /** Flush everything still buffered. Call once, when the run is over. */ close(): Promise; }