/** * Bounded read-time freshness checks for source files cited by a conclusion. * * This module intentionally depends only on Node built-ins, constants, and the * leaf path-confinement helper. It does not load the analyzer or EdgeStore; a * caller may pass the cached context's structurally-typed edge store instead. */ export interface FileHashStore { getFileHash(filePath: string): string | null; } export interface CitedFileFreshnessContext { edgeStore?: FileHashStore; /** Mtime of the exact cached artifact generation being served. */ artifactMtimeMs?: number; /** Direct callers may override the default llm-context artifact path. */ artifactPath?: string; /** The bounded payload traversal encountered a citation it could not confine. */ unsafeCitation?: boolean; } export interface CitedFileFreshnessResult { /** Normalized repository-relative files that cannot be vouched fresh. */ staleFiles: string[]; /** Confined stale paths safe to hand to a repository repair host. */ repairableStaleFiles: string[]; } export interface StaleServingDisclosure { staleFiles: string[]; note: string; repairScheduled?: true; } /** Deterministic seam for the same-handle post-read race check. */ export declare function fileChangedDuringRead(params: { opened: { dev: number; ino: number; size: number; mtimeMs: number; ctimeMs: number; }; afterRead: { size: number; mtimeMs: number; ctimeMs: number; }; namedAfterRead: { dev: number; ino: number; size: number; mtimeMs: number; ctimeMs: number; isSymbolicLink(): boolean; }; bytesRead: number; }): boolean; export interface CitedSourceFiles { files: string[]; truncated: boolean; unsafeCitation?: true; } /** * Resolve one file's dual-baseline verdict. A recorded content hash is * authoritative. Full analysis does not populate file_hashes on every path, so * an absent hash falls back to source-vs-artifact mtime. Unknown inputs fail safe. */ export declare function resolveFileFreshness(params: { baselineFileHash: string | null; currentFileHash: string; sourceMtimeMs: number; artifactMtimeMs: number; }): 'fresh' | 'stale'; /** * Collect source-file citations from a final structured payload. Calling this * after token budgeting makes the I/O bound follow what was actually emitted, * not candidates the user never sees. Traversal is iterative and capped too, so * a malformed cyclic or enormous value cannot turn freshness into a repo scan. */ export declare function collectCitedSourceFiles(value: unknown, max?: number): CitedSourceFiles; /** Apply the same count and serialized-path budget to caller-supplied citations. */ export declare function boundCitedFiles(citedFiles: Iterable, max?: number, maxPathBytes?: number): CitedSourceFiles; /** * Check only the files the caller is about to cite. Inputs are deduplicated * before I/O. Unsafe paths are represented by one conservative sentinel and are * never read, so an untrusted analysis artifact cannot escape the repository. */ export declare function checkCitedFileFreshness(root: string, citedFiles: Iterable, context?: CitedFileFreshnessContext): Promise; /** Build the additive payload block shared by MCP and one-shot CLI surfaces. */ export declare function buildStaleServingDisclosure(staleFiles: readonly string[], repairScheduled?: boolean): StaleServingDisclosure | undefined; //# sourceMappingURL=freshness.d.ts.map