import { type DeriveReviewSessionApplyResultForSnapshotResult, type MapReviewWorkbenchResultsToApplyActionsOptions, type ReviewApplyActionIssue, type ReviewApplyActionMapping, type ReviewSessionApplyIssue, type ReviewSessionApplyResolutionRequirement, type ReviewWorkbenchResult } from "./review-workbench.js"; import { type ReviewDecisionModeIssue } from "./producer-decision-mode.js"; import { type ReviewSessionReplayIssue, type ReviewSessionReplayWarning } from "./review-session-replay.js"; import type { ReviewDecision, ReviewSessionEvent } from "../review-resource.js"; import { type ReviewQueueBinding } from "./queue-binding.js"; import type { ExtractionEnvelopeImport, ExtractionEnvelopeImportResult } from "../extraction-envelope.js"; import { type ReviewQueueSessionState } from "./review-queue-session.js"; import type { ReviewPresentationAdapter } from "./review-presentation.js"; export interface ServerReviewSessionRecord { readonly sessionName: string; readonly snapshot: ReviewQueueSessionState; readonly snapshotHash: string; readonly eventCount?: number; readonly updatedAt: string; } export type ServerReviewSessionFreshnessStatus = "current" | "stale"; export interface ServerReviewSessionFreshnessComparison { readonly status: ServerReviewSessionFreshnessStatus; readonly expectedSnapshotHash: string; readonly actualSnapshotHash: string; readonly expectedEventCount?: number; readonly actualEventCount?: number; } export type ServerReviewSessionStaleIssueCode = "snapshot-hash-mismatch" | "event-count-mismatch"; export interface ServerReviewSessionStaleIssue { readonly code: ServerReviewSessionStaleIssueCode; readonly message: string; readonly expected: string | number; readonly actual: string | number; } export declare class StaleServerReviewSessionError extends Error { readonly name = "StaleServerReviewSessionError"; readonly issues: readonly ServerReviewSessionStaleIssue[]; readonly comparison: ServerReviewSessionFreshnessComparison; constructor(comparison: ServerReviewSessionFreshnessComparison); } export type ServerReviewSessionEventValidationIssue = ReviewSessionReplayIssue | { readonly code: "session-name-mismatch"; readonly eventName: string; readonly sequence: number; readonly expectedSessionName: string; readonly actualSessionName: string; readonly message: string; }; export declare class ServerReviewSessionEventValidationError extends Error { readonly name = "ServerReviewSessionEventValidationError"; readonly issues: readonly ServerReviewSessionEventValidationIssue[]; constructor(issues: readonly ServerReviewSessionEventValidationIssue[]); } export interface CreateServerReviewSessionRecordOptions { readonly sessionName: string; readonly snapshot: ReviewQueueSessionState; readonly eventCount?: number; readonly updatedAt?: string | Date; } export interface DeriveServerReviewSessionApplyResultOptions { readonly record: ServerReviewSessionRecord; readonly events: readonly ReviewSessionEvent[]; readonly currentSnapshot?: ReviewQueueSessionState; readonly currentEventCount?: number; readonly requiredResolvedItems?: ReviewSessionApplyResolutionRequirement; /** The adapter the reviewer's card used; the recorded decision prompts render the target label and values with it. */ readonly presentationAdapter?: ReviewPresentationAdapter; /** * The queue binding taken when this session opened (see * ./queue-binding.ts). When present, the apply derivation refuses unless the * record's snapshot — and the caller's current snapshot, when supplied — * still matches the bound bytes and the bound item set, both directions. * * This is the check the record's own `snapshotHash` cannot provide: a record * rebuilt from a mutated snapshot carries a hash of the mutated bytes and * agrees with itself. The binding's authority is that it was written earlier, * at queue construction, and carried unchanged — so it MUST come from the * consumer's storage, not be recomputed at call time. */ readonly binding?: ReviewQueueBinding; /** * The extraction import record the snapshot's items were built from, as * stored beside the session. When present, the derivation refuses (throws * {@link UnattestedExtractionQueueError}) unless the record's snapshot items * match it (see `validateReviewQueueAgainstExtractionImport`). When absent and * the snapshot's items carry the extraction-envelope binding, the result * carries an `unverified-extraction-queue` warning: nothing checked them. */ readonly extractionImport?: ExtractionEnvelopeImport | ExtractionEnvelopeImportResult; } export declare function createServerReviewSessionRecord(options: CreateServerReviewSessionRecordOptions): ServerReviewSessionRecord; export declare function hashReviewSessionSnapshot(snapshot: ReviewQueueSessionState): string; /** * Project the current review session state from a snapshot plus its * append-only event log: replay events over the snapshot when any exist, * otherwise return the snapshot itself unchanged (same object reference — * no eager replay, no copy). Collapses the * `events.length > 0 ? replayReviewSessionEvents(snapshot, events) : snapshot` * conditional that was duplicated across the MCP and console review * adapters (src/mcp/review-mcp.ts, src/console/review-console-server.ts) — * same shape of fix as canonicalJson in ./canonical.ts, which was * extracted after two near-identical copies of a derivation desynced * (audit 2026-06-28, ops#24). */ export declare function currentSessionState(snapshot: ReviewQueueSessionState, events: readonly ReviewSessionEvent[]): ReviewQueueSessionState; export declare function compareServerReviewSessionFreshness(record: ServerReviewSessionRecord, snapshot: ReviewQueueSessionState, eventCount?: number): ServerReviewSessionFreshnessComparison; export declare function assertServerReviewSessionFreshness(record: ServerReviewSessionRecord, snapshot: ReviewQueueSessionState, eventCount?: number): void; export declare function validateServerReviewSessionEvents(record: ServerReviewSessionRecord, events: readonly ReviewSessionEvent[]): ServerReviewSessionEventValidationIssue[]; export declare function assertServerReviewSessionEvents(record: ServerReviewSessionRecord, events: readonly ReviewSessionEvent[]): void; export declare function deriveServerReviewSessionApplyResult(options: DeriveServerReviewSessionApplyResultOptions): DeriveReviewSessionApplyResultForSnapshotResult; export interface ApplyReviewSessionOptions { /** Pre-built server record. When omitted, one is built from `snapshot`. */ readonly record?: ServerReviewSessionRecord; /** Reviewed snapshot to build a server record from when `record` is omitted. */ readonly snapshot?: ReviewQueueSessionState; /** Session name for the built record; falls back to the first event's session name. */ readonly sessionName?: string; /** `updatedAt` stamp for the built record. */ readonly recordUpdatedAt?: string | Date; readonly events: readonly ReviewSessionEvent[]; readonly currentSnapshot?: ReviewQueueSessionState; readonly currentEventCount?: number; readonly requiredResolvedItems?: ReviewSessionApplyResolutionRequirement; /** See {@link DeriveServerReviewSessionApplyResultOptions.extractionImport}. */ readonly extractionImport?: ExtractionEnvelopeImport | ExtractionEnvelopeImportResult; /** When true, each result is checked against its item's producerPolicy.decisionMode. */ readonly enforceProducerPolicy?: boolean; /** When provided, results are mapped to product apply actions in the same call. */ readonly mapActions?: Omit, "results" | "items">; } export type ApplyReviewSessionIssue = ReviewSessionApplyIssue | { readonly code: "stale-session"; readonly message: string; } | { readonly code: "invalid-events"; readonly message: string; } | { readonly code: "unattested-extraction-queue"; readonly message: string; } | { readonly code: "decision-mode-violation"; readonly reviewItemName: string; readonly message: string; readonly issues: readonly ReviewDecisionModeIssue[]; } | { readonly code: "action-mapping-failed"; readonly message: string; readonly issues: readonly ReviewApplyActionIssue[]; }; export type ApplyReviewSessionResult = { readonly ok: true; readonly issues: readonly []; /** Non-fatal replay notes, e.g. a legacy text edit converted to its typed value. */ readonly warnings?: readonly ReviewSessionReplayWarning[]; readonly decisions: readonly ReviewDecision[]; readonly results: readonly ReviewWorkbenchResult[]; readonly actions: readonly ReviewApplyActionMapping[]; readonly replayedSession: ReviewQueueSessionState; } | { readonly ok: false; readonly issues: readonly ApplyReviewSessionIssue[]; readonly decisions: readonly ReviewDecision[]; readonly results: readonly ReviewWorkbenchResult[]; readonly actions: readonly ReviewApplyActionMapping[]; }; /** * One-call server apply: collapses the "resolve server record → derive apply * result → normalize freshness/event errors → (optionally) enforce * producerPolicy.decisionMode → (optionally) map results to product actions" * choreography into a single call. * * Returns a discriminated `{ ok }` result rather than throwing for expected * failure modes (stale session, invalid events, unresolved items, decision-mode * violations, action-mapping failures) — matching the * `deriveReviewSessionApplyResultForSnapshot` idiom. Unexpected errors still * propagate. * * Supply either a pre-built `record` or a `snapshot` (a record is then built via * `createServerReviewSessionRecord`). `enforceProducerPolicy` is off by default; * unset `producerPolicy`/`decisionMode` never changes behavior. */ export declare function applyReviewSession(options: ApplyReviewSessionOptions): ApplyReviewSessionResult;