/** * Typed-event conformance stats for one parsed adapter stream. Shared by the * per-adapter fixture parity tests: every adapter must emit schema-valid * events, tool_results MUST carry a status (a statusless result is treated as * dropped/diagnostic by the engine, never as ok), and streams that perform * tool work must surface typed tool_call/tool_result pairs. */ export interface StreamConformanceStats { total: number; started: number; messages: number; toolCalls: number; toolResults: number; statuslessToolResults: number; errorToolResults: number; deniedToolResults: number; cancelledToolResults: number; fileChanges: number; usageEvents: number; errors: number; completed: number; } /** Validate every event against the HarnessEvent schema and aggregate stats. */ export declare function validateTypedStream(events: unknown[]): StreamConformanceStats; /** * Per-fixture STREAM SEMANTICS expectations (W3.8): the fixture manifest * declares them next to provenance, and every adapter conformance test * asserts them through this one owner — finality/dedup/lifecycle regressions * (the "fixed it three times" class) change these counts on a deterministic * fixture and fail loudly instead of shipping. `final_source` documents the * vendor mechanism for humans; every other field is machine truth. */ export interface FixtureStreamExpectations { /** Exact count of `final: true` messages (the typed final answer). */ final_messages?: number; /** * The typed identity of the wire event finality came from — the adapter * stamps `payload.final_source` on every final message ("result", * "structured_output", "last_agent_message", "assistant_message"). Machine-checked: a parser * that starts finalizing from a different wire event fails this even when * the count and position happen to survive (final sol review #5). */ final_source?: string; /** * Whether the typed final is the LAST message of the stream. Finality comes * from the vendor's TERMINAL event: a parser that marks mid-run narration * final keeps the count right while answering from the wrong event, and only * this catches it. */ final_is_last_message?: boolean; /** Exact count of thinking events — lifecycle frames must never inflate it. */ thinking_events?: number; /** * Exact count of normalized run-level `started` events. Some vendors emit * more than one native lifecycle frame per run (codex `--json` pairs * `thread.started` with `turn.started`); the adapter must collapse them to * ONE normalized start, and only an exact count catches a regression that * re-emits the duplicate. */ started_events?: number; /** Exact count of display-stream delta chunks (payload.delta === true). */ delta_messages?: number; /** Exact count of typed error tool results. */ tool_error_results?: number; /** Whether the stream surfaces a typed rate_limit signal. */ typed_rate_limit?: boolean; /** * Typed retry classification the stream must carry — the vendor category on * a transient `status` event, or `rate_limit` from the rate-limit signal * (e.g. "rate_limit"). Presence alone is not the contract: the CLASS is what * bounded-retry policy consumes, and a regression that keeps the signal but * loses its category passes a presence check. */ retry_class?: string; } /** Violations of the declared expectations over an already-parsed stream. */ export declare function streamExpectationViolations(events: unknown[], expectations: FixtureStreamExpectations): string[]; //# sourceMappingURL=conformance.d.ts.map