/** * Transport-safe evidence-stream pagination for the spec-workflow composites. * * A composite response is an ORDERED STREAM of logical evidence records — * domain membership, signatures, each inventory family, relationships, spec * segments, mapping observations, drift, structural changes, overlaps. A page * packs records from the stream until the SERIALIZED envelope approaches the * effective byte budget, and the cursor records the stream section plus the * offset inside it (change `harden-spec-workflow-lifecycle`, decision c9598b6f). * * Why bytes and not tokens: tokenizers vary by host and model, so a token * estimate cannot guarantee a transport limit. Serialized UTF-8 bytes are the * enforcement unit; a token estimate may be reported alongside, never enforced. * * Why a section+offset cursor and not a file offset: a single oversized file can * contribute more signatures or relationships than one page holds. A file-offset * cursor would make the remainder of that file's evidence unreachable; a * section+offset cursor continues INSIDE the section instead. */ /** Bumped whenever the cursor payload or packing contract changes. */ export declare const EVIDENCE_STREAM_PROTOCOL = 1; /** * Default serialized budget: 48 KiB. * * Every bundled adapter must be able to carry a full page without its own * truncation. Pi clips model-visible tool text at 50,000 characters, so the * default sits below that boundary with room for the adapter's own framing. */ export declare const DEFAULT_RESPONSE_BYTES: number; /** Server maximum. A caller may request less, never more. */ export declare const MAX_RESPONSE_BYTES: number; /** Floor, so a caller cannot request a budget no page could ever satisfy. */ export declare const MIN_RESPONSE_BYTES: number; /** Clamp a caller-supplied budget into the server's range. */ export declare function clampResponseBytes(value?: number): number; /** One logical section of the stream: an ordered, independently pageable list. */ export interface EvidenceSection { /** Stable section name, as it appears in receipts and cursors. */ section: string; records: unknown[]; } /** * The cursor payload. Short keys keep the encoded cursor small, since it is * carried inside the very budget it governs. */ export interface EvidenceCursorPayload { /** Protocol version. */ v: number; /** Workflow. */ w: string; /** Requested domain. */ d: string; /** Analysis generation identity the page was built from. */ g: string; /** Fingerprint of every stable input that shapes the logical evidence stream. */ x: string; /** Index into the ordered section list. */ s: number; /** Offset inside that section. */ o: number; /** Effective byte budget bound into the cursor. */ b: number; /** Effective per-page item limit. */ m: number; /** Canonical repair base ref; empty for generation. */ r: string; /** Fingerprint over the fields above, so a forged cursor is rejected. */ f: string; } export interface EvidenceStreamPosition { sectionIndex: number; offset: number; } export interface EvidencePage { /** Sections with at least one record on this page, in stream order. */ included: string[]; /** Sections wholly or partly deferred, with the number of records deferred. */ omitted: Array<{ section: string; reason: string; omittedCount: number; }>; /** Records selected for this page, keyed by section name. */ records: Record; /** Offset each included section started at, so a trim can recompute the cursor. */ starts: Record; /** Where the next page resumes. Absent when the stream is exhausted. */ next?: EvidenceStreamPosition; /** * Set when one indivisible record cannot fit in an empty page at this budget. * The caller must return a typed unrecoverable error rather than silently * dropping the record or declaring the workflow complete. */ unrepresentable?: { section: string; offset: number; bytes: number; }; } export declare function encodeEvidenceCursor(payload: Omit): string; /** * Decode and authenticate a cursor. * * Returns `undefined` for anything that is not a well-formed cursor this server * issued at this protocol version: a forged, truncated, or hand-edited cursor is * rejected rather than partially honored. Binding the budget into the * fingerprint also stops a caller from replaying a cursor at a larger budget * than the page it continues. */ export declare function decodeEvidenceCursor(value?: string): EvidenceCursorPayload | undefined; /** * Pack the stream into one page that fits `budget` serialized bytes. * * `envelopeBytes` is the size of everything on the page that is NOT stream * records — identity, provenance, receipt scaffolding, and a reserve for the * continuation cursor. Records are admitted while the running total stays within * the budget; the caller performs the exact final measurement and may re-pack at * a smaller budget, which is why this stays linear. */ export declare function packEvidenceStream(sections: EvidenceSection[], start: EvidenceStreamPosition, budget: number, envelopeBytes: number, maxItems?: number): EvidencePage; /** * Trim the last records off a packed page until the EXACT serialized envelope * fits the budget, returning the trimmed records to the stream. * * The packer works from per-record estimates; this is the authoritative check. * Returns `false` when even an empty page cannot fit, which is an unrecoverable * transport condition for the caller to report. */ export declare function trimPageToBudget(page: EvidencePage, sections: EvidenceSection[], budget: number, measure: (page: EvidencePage) => number): boolean; //# sourceMappingURL=evidence-stream.d.ts.map