/** * The expected-submission set: what a step emission OWES, stated by name. * * A fan-out emission used to be implicit — it wrote N lane prompts and, on the * next turn, simply looked to see which result files happened to be there. An * absent lane was a `continue`, so a lane that was never delivered was * indistinguishable from a lane that was merely slow, and the run reported * neither the shortfall nor its cause. Recording the set at emit turns that * into "expected 3, accepted 2, lane `revealed` is missing". * * The set is a COHERENCE grouping, never a fit claim: a member is a * content-coherent lane, and the diff counts lanes. Nothing here describes a * backend, a window, or a partition sized to one — that is the host's business * and this package does not own it. * * Storage-neutral by construction (one core, two draws): the core says what the * set IS; the audit draw persists it as a file beside the submissions, the * remediate draw carries its equivalent inside `RemediationState`. */ import type { SubmissionIssue, SubmissionReadOutcome } from "./submissionClassifier.js"; import type { SubmissionRoots } from "./submissionIdentity.js"; export declare const EXPECTED_SET_CONTRACT_VERSION: "submission-expected-set/v1alpha1"; export interface ExpectedSubmission { readonly submission_id: string; /** The content-coherent lane this member answers. */ readonly lane: string; /** Digest of the prompt the lane was given — binds the answer to the ask. */ readonly prompt_sha256: string; /** The tool-computed bound path, repository-relative and forward-slashed. */ readonly submission_path: string; } export interface ExpectedSubmissionSet { readonly contract_version: typeof EXPECTED_SET_CONTRACT_VERSION; readonly run_id: string; readonly entries: readonly ExpectedSubmission[]; } /** One lane's declaration, as the emitter knows it. */ export interface ExpectedSubmissionLane { readonly lane: string; readonly submissionId: string; readonly promptSha256: string; /** * False for a lane whose submission the TOOL never reads — a host-side * intermediate another lane consumes (the conceptual perspectives, which only * the judge reads). Declared so the builder below can REFUSE one rather than * mint an expectation that can never be satisfied or dropped. Absent/true is * the ordinary lane. */ readonly expected?: boolean; } /** Per-member verdict of a diff. */ export type SubmissionClassification = { readonly status: "accepted"; readonly submission_id: string; } | { readonly status: "issue"; readonly submission_id: string; readonly issue: SubmissionIssue; }; export interface ExpectedSetDiff { /** How many lanes were owed. */ readonly expected: number; /** How many of them arrived. */ readonly accepted: number; readonly members: readonly SubmissionClassification[]; } /** * Build the set one emission owes. Entries are ordered by `submission_id` — a * content-derived key, never emission or filesystem order, so re-recording an * unchanged set produces byte-identical content. * * A lane declaring `expected: false` is REFUSED here, at the ONE seam every * emitter builds its set through: the tool never reads that lane's submission, * so an expectation recorded against it can never be satisfied or dropped — * it would accumulate as a permanent, false shortfall the run reports forever. * Throwing (not filtering) is the fail-closed shape: a caller that routes its * un-expected lanes through this builder anyway has misstated what it owes, * and a silently narrowed set would hide exactly that. The audit draw's * materializer filters at its own boundary first; this is the backstop that * makes the filter's omission non-optional. */ export declare function buildExpectedSubmissionSet(params: { readonly runId: string; readonly paths: SubmissionRoots; readonly lanes: readonly ExpectedSubmissionLane[]; }): ExpectedSubmissionSet; /** * Merge `additional` into `base`, keyed by `submission_id`. A re-emitted lane * re-declares the identical member (the id is deterministic), and a step that * materializes several lane groups accumulates them into one statement of what * is currently owed. Returns the merged set plus the ids that are NEW, so a * caller records an `expected` event once per lane rather than on every * re-emission. */ export declare function mergeExpectedSets(base: ExpectedSubmissionSet | undefined, additional: ExpectedSubmissionSet): { readonly set: ExpectedSubmissionSet; readonly addedIds: readonly string[]; }; /** Drop members that are no longer owed (they were accepted and applied). */ export declare function withoutExpectedSubmissions(set: ExpectedSubmissionSet, submissionIds: readonly string[]): ExpectedSubmissionSet; /** * Diff what was owed against what is on disk. Every member is classified by its * own id: arrived, or named with the reason it did not. */ export declare function diffExpectedSet(set: ExpectedSubmissionSet, observed: ReadonlyMap): ExpectedSetDiff; //# sourceMappingURL=expectedSubmissions.d.ts.map