import { type CandidateRequest, type ReviewPayloadFs } from "./review-payload"; export type ReviewPersistFs = Omit & { writeFileSync(path: string, data: Uint8Array, options: { flag: "wx"; mode: number; }): void; mkdirSync(path: string): void; renameSync(oldPath: string, newPath: string): void; unlinkSync(path: string): void; rmSync?(path: string, options: { recursive: true; force: true; }): void; linkSync?(existingPath: string, newPath: string): void; }; export type PersistOptions = { reviewStateRoot: string; fs?: ReviewPersistFs; }; export type DocumentSection = { heading: string; body: string; }; export type DocumentInput = { reviewRoot: string; headSha: string; sections: DocumentSection[]; frontmatterYaml?: string; }; export type InputInput = { reviewRoot: string; input: object; }; export type MetaInput = { reviewRoot: string; headSha: string; meta: object; name?: string; }; export type FactsInput = { reviewRoot: string; facts: object; }; export type CandidateInput = { reviewRoot: string; candidate: CandidateRequest; }; export type ReadDocumentInput = { reviewRoot: string; headSha: string; }; export type PersistRejection = { ok: false; reason: "invalid-arguments" | "invalid-op" | "invalid-review-state-root" | "invalid-head-sha" | "invalid-json" | "invalid-yaml" | "invalid-document" | "ambiguous-document" | "unknown-field" | "missing-field" | "invalid-field" | "chunk-field-collision" | "unbreakable-line" | "line-too-long" | "path-outside-root" | "path-resolution-error" | "not-regular-file" | "symlink-target" | "write-error" | "read-error" | "encoding-error" | "readback-mismatch" | "cleanup-error" | "unknown-record" | "not-found" | "unknown-staging" | "incomplete-staging" | "chunk-too-large" | "heading-conflict" | "part-count-conflict" | "part-type-conflict" | "merge-conflict"; expectedBytes?: number; actualBytes?: number; length?: number; missing?: StagingGap[]; unexpected?: Array; }; export type WriteResult = PersistRejection | { ok: true; path: string; sha256: string; lines: number; bytes: number; }; export type ReadDocumentResult = PersistRejection | { ok: true; sections: DocumentSection[]; frontmatterYaml: string | null; sha256: string; lines: number; }; export type ReadFactsResult = PersistRejection | { ok: true; facts: object; sha256: string; lines: number; }; /** * Repo spelling and the branch (or detached head SHA) are read before path I/O. * Invalid repo/empty branch inputs reject; every non-slug character becomes one * hyphen, leaving a single local namespace component. No override disables this * derivation; resolveReviewDirectory still enforces filesystem containment. */ export declare function localReviewNamespace(repo: string, branch: string): string; type DirectoryReason = "invalid-review-state-root" | "path-outside-root" | "path-resolution-error" | "not-found"; export declare class ReviewDirectoryError extends Error { readonly reason: DirectoryReason; readonly path: string; constructor(reason: DirectoryReason, path: string, cause?: unknown); } type DirectoryFs = Pick; export declare const isReviewPath: (path: string) => boolean; export declare const isLegacyReviewPath: (path: string) => boolean; /** * The host workspace and real directory chain are the containment oracle. Check * the requested namespace before mkdir, then check each ancestor before creating * its child and recheck before descent. Host-root components cannot redirect via * symlinks; namespace symlinks must stay inside that root. Persist writers and * lock.acquire create missing directories; reads/release never do. Invalid paths * fail closed for every consumer, with no bypass. Preflight cannot prevent a * concurrent directory replacement between checks and filesystem operations. * A .corvus host root admits only reviews/ or tasks//reviews/; * this layout is checked before descent. Legacy namespaces are read-only, and * symlinked directories under the widened host root reject instead of admitting task files. */ export declare function resolveReviewDirectory(reviewRoot: string, reviewStateRoot: string, fs: DirectoryFs, create: boolean): { root: string; path: string; }; /** An empty first heading represents the title/preamble; other headings are H2 labels. */ export declare function write_document(input: DocumentInput, opts: PersistOptions): WriteResult; export declare function write_input(input: InputInput, opts: PersistOptions): WriteResult; export declare function write_meta(input: MetaInput, opts: PersistOptions): WriteResult; /** * The verdict module supplies computed data before serialization and mutation. * Only this internal entry point selects verdict.yaml; write_meta's tool allowlist * stays unchanged. Containment, serialization and byte-readback failures reject * through the shared writer, with no caller-controlled path or validation bypass. */ export declare function writeVerdictRecord(input: { reviewRoot: string; headSha: string; verdict: object; }, opts: PersistOptions): WriteResult; export declare function write_facts(input: FactsInput, opts: PersistOptions): WriteResult; export declare function read_facts(input: { reviewRoot: string; }, opts: PersistOptions): ReadFactsResult; export declare function write_candidate(input: CandidateInput, opts: PersistOptions): WriteResult; export declare function read_document(input: ReadDocumentInput, opts: PersistOptions): ReadDocumentResult; export type StagingGap = { index?: number; key?: string; parts?: number[]; }; type CandidateAnchor = Omit; type CandidatePart = { comment?: number; field: "path" | "body"; anchor?: CandidateAnchor; }; type StagedPart = Partial & { index?: number; key?: string; path?: string[]; part: number; parts: number; heading?: string; file: string; bytes: number; sha256: string; }; export type StagingResult = PersistRejection | { ok: true; staging_id: string; replaced_stale?: boolean; received?: StagedPart[]; missing?: StagingGap[]; } | (Extract & { sections?: number; keys?: string[]; parts?: number; staged_bytes?: number; cleanup_pending?: boolean; }); export declare const begin: (input: unknown, opts: PersistOptions) => StagingResult; export declare const append: (input: unknown, opts: PersistOptions) => StagingResult; export declare const finalize: (input: unknown, opts: PersistOptions) => StagingResult; export declare const abort: (input: unknown, opts: PersistOptions) => StagingResult; export declare const status: (input: unknown, opts: PersistOptions) => StagingResult; /** Host-only options permit filesystem injection; tool arguments cannot supply them. */ export declare function createPersistExecutor(reviewStateRoot: string, options?: Omit): (input: unknown) => string; export {}; //# sourceMappingURL=review-persist.d.ts.map