export type InodeId = bigint;
export type ExtentId = bigint;
export type MetadataFile = "a" | "b";
export declare function otherMetadataFile(file: MetadataFile): MetadataFile;
interface BaseInode {
    id: InodeId;
    mode: number;
    atimeMs: bigint;
    mtimeMs: bigint;
    ctimeMs: bigint;
}
export interface DirectoryInode extends BaseInode {
    kind: "directory";
    children: Map<string, InodeId>;
}
export interface FileInode extends BaseInode {
    kind: "file";
    size: bigint;
    extents: ExtentId[];
}
/**
 * A symbolic link. It owns no extents and no children — the whole entry IS its absolute `target`,
 * which path resolution restarts the walk at. See {@link validateSymlinkTarget} for why relative
 * targets are refused.
 */
export interface SymlinkInode extends BaseInode {
    kind: "symlink";
    target: string;
}
export type Inode = DirectoryInode | FileInode | SymlinkInode;
export interface OrphanRecord {
    inodeId: InodeId;
    mode: number;
    atimeMs: bigint;
    mtimeMs: bigint;
    ctimeMs: bigint;
    size: bigint;
    extents: ExtentId[];
}
export declare function makeOrphanRecord(inode: FileInode): OrphanRecord;
export declare class IndexedExtentSet {
    #private;
    get size(): number;
    has(extentId: ExtentId): boolean;
    add(extentId: ExtentId): void;
    delete(extentId: ExtentId): boolean;
    values(): readonly ExtentId[];
    peekLast(count: number): ExtentId[];
    clone(): IndexedExtentSet;
}
export interface AllocatorState {
    totalExtents: bigint;
    ownedBy: Map<ExtentId, InodeId>;
    available: IndexedExtentSet;
    quarantine: Map<ExtentId, bigint | null>;
}
export interface VfsState {
    generation: bigint;
    nextInodeId: bigint;
    rootInodeId: bigint;
    extentSize: number;
    activeMetadataFile: MetadataFile;
    retainedGenerations: Record<MetadataFile, bigint | null>;
    basePayloadBytes: number;
    inodes: Map<InodeId, Inode>;
    parentByInode: Map<InodeId, {
        parentId: InodeId;
        name: string;
    }>;
    allocator: AllocatorState;
}
export interface CreateDirectoryChoice {
    parentId: InodeId;
    name: string;
    inodeId: InodeId;
    mode: number;
    atimeMs: bigint;
    mtimeMs: bigint;
    ctimeMs: bigint;
}
export interface ExtentRun {
    start: ExtentId;
    count: number;
}
export type TxnRecord = {
    kind: "createDirectories";
    entries: readonly CreateDirectoryChoice[];
} | {
    kind: "createFile";
    parentId: InodeId;
    name: string;
    inodeId: InodeId;
    mode: number;
    atimeMs: bigint;
    mtimeMs: bigint;
    ctimeMs: bigint;
    size: bigint;
    extents: readonly ExtentRun[];
} | {
    kind: "removeFile";
    parentId: InodeId;
    name: string;
    parentMtimeMs: bigint;
    parentCtimeMs: bigint;
} | {
    kind: "changeMode";
    inodeId: InodeId;
    mode: number;
    ctimeMs: bigint;
} | {
    kind: "changeTimes";
    inodeId: InodeId;
    atimeMs: bigint;
    mtimeMs: bigint;
    ctimeMs: bigint;
} | {
    kind: "resizeFile";
    operation: "truncate" | "write";
    inodeId: InodeId;
    size: bigint;
    allocated: readonly ExtentRun[];
    mtimeMs: bigint;
    ctimeMs: bigint;
} | {
    kind: "removeDirectory";
    parentId: InodeId;
    name: string;
    parentMtimeMs: bigint;
    parentCtimeMs: bigint;
} | {
    kind: "rename";
    sourceParentId: InodeId;
    sourceName: string;
    destinationParentId: InodeId;
    destinationName: string;
    timestampMs: bigint;
} | {
    kind: "createSymlink";
    parentId: InodeId;
    name: string;
    inodeId: InodeId;
    mode: number;
    atimeMs: bigint;
    mtimeMs: bigint;
    ctimeMs: bigint;
    target: string;
} | {
    kind: "reserveQuarantine";
    extents: readonly ExtentRun[];
};
export interface TxnPlan<RecordType extends TxnRecord = TxnRecord> {
    record: RecordType;
}
export interface PreflightLimits {
    maxFramePayloadBytes: number;
    maxBasePayloadBytes: number;
}
/** The mode a symbolic link carries: `S_IFLNK | 0777`, the only mode POSIX gives a link. */
export declare const SYMLINK_MODE = 41471;
export declare function estimateMetadataBasePayloadBytes(state: VfsState): number;
export declare function estimateTxnPayloadBytes(record: TxnRecord): number;
export declare function preflightTxn(state: VfsState, record: TxnRecord, limits?: PreflightLimits): number;
declare const PREPARED_TXN_PROJECTION: unique symbol;
export interface PreparedTxnProjection {
    readonly projectedBasePayloadBytes: number;
    readonly state: VfsState;
    readonly record: TxnRecord;
    readonly [PREPARED_TXN_PROJECTION]: true;
}
/** @internal Bind one projected size to the exact live state and record it preflighted. */
export declare function prepareTxnProjection(state: VfsState, record: TxnRecord): PreparedTxnProjection;
export declare function createInitialState(extentSize: number): VfsState;
export declare function toExtentRuns(extents: readonly ExtentId[]): ExtentRun[];
export declare function expandExtentRuns(runs: readonly ExtentRun[], maximum: number): ExtentId[];
export declare function getInodeAtPath(state: VfsState, path: string): Inode;
/**
 * Resolve every symbolic link on `path` and report the link-free absolute path it names.
 *
 * `follow` governs the FINAL component only — the POSIX `stat`/`lstat` split. Every INTERMEDIATE
 * link is always followed, because a path can only continue through the thing a link points at.
 *
 * A component that does not exist, or one whose parent turned out not to be a directory, stops the
 * walk and the remainder is carried through verbatim: resolution answers "which path does this
 * name", not "does it exist". The operation that follows reports `ENOENT`/`ENOTDIR` itself, or
 * creates the tail — which is exactly what an `open(O_CREAT)` through a symlinked directory needs.
 *
 * Targets are absolute, so a hop restarts the walk at the root. `MAX_SYMLINK_HOPS` hops is `ELOOP`,
 * and each expansion is re-validated by `parsePath`, so a chain that outgrows the store's depth or
 * byte limits is rejected here rather than in a planner.
 */
export declare function resolveLinks(state: VfsState, path: string, follow: boolean): string;
export declare function planMkdir(state: VfsState, path: string, options: {
    recursive?: boolean;
    mode?: number;
    nowMs: bigint;
}): TxnPlan<Extract<TxnRecord, {
    kind: "createDirectories";
}>>;
export declare function planCreateFile(state: VfsState, path: string, options: {
    mode?: number;
    nowMs: bigint;
    size?: bigint;
}): TxnPlan<Extract<TxnRecord, {
    kind: "createFile";
}>>;
/** A symbolic link. Nothing about the TARGET is consulted — the link entry is the whole record. */
export declare function planSymlink(state: VfsState, path: string, target: string, options: {
    mode?: number;
    nowMs: bigint;
}): TxnPlan<Extract<TxnRecord, {
    kind: "createSymlink";
}>>;
/** Removes a FILE or a SYMBOLIC LINK. A link is unlinked as itself; its target is never touched. */
export declare function planUnlink(state: VfsState, path: string, nowMs: bigint): TxnPlan<Extract<TxnRecord, {
    kind: "removeFile";
}>>;
export declare function planChmod(state: VfsState, path: string, mode: number, nowMs: bigint): TxnPlan<Extract<TxnRecord, {
    kind: "changeMode";
}>>;
export declare function planUtimes(state: VfsState, path: string, atimeMs: bigint, mtimeMs: bigint, ctimeMs: bigint): TxnPlan<Extract<TxnRecord, {
    kind: "changeTimes";
}>>;
export declare function planResizeFile(state: VfsState, path: string, size: bigint, nowMs: bigint, operation: "truncate" | "write"): TxnPlan<Extract<TxnRecord, {
    kind: "resizeFile";
}>>;
/** @internal Inode-first planner for descriptor operations that already resolved the file. */
export declare function planResizeFileForInode(state: VfsState, inode: FileInode, size: bigint, nowMs: bigint, operation: "truncate" | "write"): TxnPlan<Extract<TxnRecord, {
    kind: "resizeFile";
}>>;
export declare function planRmdir(state: VfsState, path: string, nowMs: bigint): TxnPlan<Extract<TxnRecord, {
    kind: "removeDirectory";
}>>;
export declare function planRename(state: VfsState, oldPath: string, newPath: string, nowMs: bigint): TxnPlan<Extract<TxnRecord, {
    kind: "rename";
}>>;
export declare function planReserveQuarantine(state: VfsState, count: number): TxnPlan<Extract<TxnRecord, {
    kind: "reserveQuarantine";
}>>;
export declare function applyTxn(state: VfsState, record: TxnRecord, prepared?: PreparedTxnProjection): void;
export declare function projectRepack(state: VfsState, pinnedQuarantine?: ReadonlySet<ExtentId>): VfsState;
/**
 * @internal Activation-only projection. Structures repack never mutates are shared read-only until
 * durable activation; allocator and generation structures remain isolated from the live state.
 */
export declare function projectRepackForActivation(state: VfsState, pinnedQuarantine?: ReadonlySet<ExtentId>): VfsState;
export declare function validateState(state: VfsState): void;
export declare function canonicalStateView(state: VfsState): {
    generation: bigint;
    nextInodeId: bigint;
    rootInodeId: bigint;
    extentSize: number;
    activeMetadataFile: MetadataFile;
    retainedGenerations: {
        a: bigint | null;
        b: bigint | null;
    };
    basePayloadBytes: number;
    inodes: ({
        id: InodeId;
        mode: number;
        atimeMs: bigint;
        mtimeMs: bigint;
        ctimeMs: bigint;
        kind: "directory";
        children: [string, bigint][];
    } | {
        id: InodeId;
        mode: number;
        atimeMs: bigint;
        mtimeMs: bigint;
        ctimeMs: bigint;
        kind: "file";
        size: bigint;
        extents: bigint[];
    } | {
        id: InodeId;
        mode: number;
        atimeMs: bigint;
        mtimeMs: bigint;
        ctimeMs: bigint;
        kind: "symlink";
        target: string;
    })[];
    parentByInode: [bigint, {
        parentId: InodeId;
        name: string;
    }][];
    allocator: {
        totalExtents: bigint;
        ownedBy: [bigint, bigint][];
        available: bigint[];
        quarantine: [bigint, bigint | null][];
    };
};
export {};
//# sourceMappingURL=state-machine.d.ts.map