import type { JournalEntry } from "./types.js"; /** The storage decision for each journal field; `satisfies` makes schema drift a type error. */ export declare const JOURNAL_ENTRY_STORAGE: { hash: "column"; size: "column"; syncedAt: "column"; direction: "column"; message: "side-table"; kind: "column"; createdBySub: "column"; remoteEtag: "column"; mtimeMs: "column"; ctimeMs: "column"; removedAt: "side-table"; removedReason: "side-table"; localDeleteIntent: "side-table"; outOfScopeProtected: "column"; skillMetadataPending: "column"; localDiverges: "column"; }; export interface JournalRowChange { readonly rowId: number; readonly path: string; readonly hadPrevious: boolean; readonly previousFingerprint: number | undefined; } export interface JournalRowStoreOptions { /** Retain row-level before-images so callers can derive a delta. Defaults to true. */ trackChanges?: boolean; } /** * A compact, insertion-ordered directory-prefix index. The immutable bulk is * stored in packed row-id ranges; only rows structurally changed after the * index was built need JavaScript sets. */ interface JournalPrefixIndex { readonly prefixIds: Map; readonly offsets: Uint32Array; readonly rowIds: Uint32Array; readonly changedRows: Set; readonly appendedRows: Map>; nextPrefixId: number; } /** * The packed row sections carried by HQSNAP4. Typed arrays are intentionally * views: the snapshot decoder installs them without decoding rows into objects. */ export interface JournalRowStoreSnapshot { readonly rowCount: number; readonly hashes: Uint8Array; readonly remoteEtags: Uint8Array; readonly sizes: Float64Array; readonly mtimes: Float64Array; readonly ctimes: Float64Array; readonly syncedAts: Float64Array; readonly flags: Uint16Array; readonly createdBySubs: Uint32Array; readonly dirIds: Uint32Array; readonly leaves: Uint32Array; readonly propertyOrderIds: Uint16Array; readonly iterationNext: Int32Array; readonly iterationPrevious: Int32Array; readonly leafBlob: Uint8Array; readonly buckets: Uint32Array; readonly directories: readonly string[]; readonly authors: readonly string[]; readonly propertyOrders: readonly (readonly string[])[]; readonly hashFallbacks: readonly (readonly [number, string])[]; readonly etagFallbacks: readonly (readonly [number, string])[]; readonly syncedAtFallbacks: readonly (readonly [number, string])[]; readonly leafFallbacks: readonly (readonly [number, string])[]; readonly removedAts: readonly (readonly [number, string])[]; readonly removedReasons: readonly (readonly [number, NonNullable])[]; readonly localDeleteIntents: readonly (readonly [number, LocalDeleteIntent])[]; readonly messages: readonly (readonly [number, string])[]; } type LocalDeleteIntent = NonNullable; /** Compact before-image used by the dirty log to avoid retaining row objects. */ export declare function journalEntryFingerprint(entry: Readonly): number; /** * The record-like view used by internal callers. It has no object-indexing * semantics: paths and rows are materialised only at the operation boundary. */ export declare class JournalRows { private readonly store; constructor(store: JournalRowStore); get size(): number; get(path: string): Readonly | undefined; has(path: string): boolean; set(path: string, entry: JournalEntry): void; delete(path: string): boolean; entries(): IterableIterator<[string, Readonly]>; keys(): IterableIterator; values(): IterableIterator>; toRecord(): Record; } /** Compact skip-gate fields; implemented by the bounded disk cache. */ export interface JournalStatFingerprint { hash: string; size: number; mtimeMs?: number; ctimeMs?: number; kind?: "file" | "symlink"; localDiverges?: boolean; removedAt?: string; localDeleteIntent?: JournalEntry["localDeleteIntent"]; } /** The read-only portion of a journal row collection that an overlay can borrow. */ export interface JournalRowSource { get(path: string): Readonly | undefined; has(path: string): boolean; keys(): IterableIterator; statFingerprint?(path: string): JournalStatFingerprint | undefined; applyDurableDelta?(upserts: Readonly>, deletes: readonly string[]): void; } /** * Internal journal-row surface. Callers use this instead of record indexing so * a packed store can retain its one resident copy all the way through a pass. */ export interface JournalRowsView extends JournalRowSource { readonly size: number; set(path: string, entry: JournalEntry): void; delete(path: string): boolean; entries(): IterableIterator<[string, Readonly]>; values(): IterableIterator>; toRecord(): Record; } /** The compact before-image a record-shaped overlay needs to build a delta. */ export interface JournalRowOverlayChange { readonly path: string; readonly hadPrevious: boolean; readonly previousFingerprint: number | undefined; } /** * A mutable, record-compatible overlay over immutable journal rows. * * The base remains the one resident packed store. Only paths a caller changes * are copied into this map, and the dirty log carries fingerprints rather than * materialized before-images. `keys()` deliberately walks the base lazily: a * caller that asks for all keys pays for that enumeration, but constructing an * overlay does not. */ export declare class JournalRowOverlay implements JournalRowsView { private readonly base; private readonly changes; /** Base keys deleted then reinserted must move to the record's tail. */ private readonly moved; private readonly dirtyPaths; private dirtyLog; constructor(base: JournalRowSource); get size(): number; get(path: string): Readonly | undefined; statFingerprint(path: string): JournalStatFingerprint | undefined; has(path: string): boolean; set(path: string, entry: JournalEntry): void; delete(path: string): boolean; keys(): IterableIterator; entries(): IterableIterator<[string, Readonly]>; values(): IterableIterator>; entriesForPrefix(prefix: string): IterableIterator<[string, Readonly]>; toRecord(): Record; dirtyLogSnapshot(): readonly JournalRowOverlayChange[]; drainDirtyLog(): JournalRowOverlayChange[]; /** * Return a new durable view without adding the delta to this caller-owned * dirty log. The source overlay stays immutable for a full pass that already * borrowed it as its read baseline. */ withCommittedDelta(upserts: Readonly>, deletes: readonly string[]): JournalRowOverlay; private entriesForPrefixByKey; private recordDirty; private setReplacement; } /** * A struct-of-arrays store for resident journal rows. It deliberately owns no * file format or proxy boundary; those arrive in later journal phases. */ export declare class JournalRowStore { private hashes; private remoteEtags; private sizes; private mtimes; private ctimes; private syncedAts; private flags; private createdBySubs; private dirIds; private leaves; private propertyOrderIds; private iterationNext; private iterationPrevious; private leafBlob; private leafLength; private buckets; private readonly directories; private readonly directoryIds; /** * Prefix candidates are valuable only to a prefix scan. Snapshot recovery * also constructs row stores for whole-journal writers (notably the short * reverse shadow), where building this index would add an O(rows) pause to * an operation that never queries a prefix. Build its packed ranges at an * explicit warm boundary or on the first scan, then retain only structural * changes in the small mutable overlay. */ private prefixRows; private readonly authors; private readonly authorIds; private readonly freeRows; private readonly freeRowSet; private readonly hashFallbacks; private readonly etagFallbacks; private readonly syncedAtFallbacks; private readonly leafFallbacks; private readonly removedAts; private readonly removedReasons; private readonly localDeleteIntents; private readonly messages; private readonly propertyOrders; private readonly propertyOrderIdsByLayout; private dirtyLog; private readonly dirtyPaths; private trackChanges; private nextRowId; private liveRows; private firstIterationRowId; private lastIterationRowId; readonly rows: JournalRows; constructor(options?: JournalRowStoreOptions); constructor(initialCapacity?: number, options?: JournalRowStoreOptions); get size(): number; /** Start retaining caller mutations after a snapshot has established its baseline. */ enableChangeTracking(): void; /** Exposed for diagnostics and path-identity tests; id zero is the root directory. */ get directoryCount(): number; get(path: string): Readonly | undefined; /** * Skip-gate fields from packed columns. Does not decode a `JournalEntry`. */ statFingerprint(path: string): JournalStatFingerprint | undefined; has(path: string): boolean; /** Internal packed-row identity for side indexes that must not retain paths. */ rowIdFor(path: string): number | undefined; /** Iterate live row identities in the same order as the record boundary. */ rowIds(): IterableIterator; /** Reconstruct one live path only when a caller needs to expose it. */ pathForRowId(rowId: number): string; /** Remove all rows and pending changes so the store can be reused cleanly. */ clear(): void; /** Replace the packed rows from a legacy record at its conversion boundary. */ replaceFromRecord(files: Readonly>): void; set(path: string, entry: JournalEntry, propertyOrder?: string[]): void; delete(path: string): boolean; entries(): IterableIterator<[string, Readonly]>; keys(): IterableIterator; entriesForPrefix(prefix: string): IterableIterator<[string, Readonly]>; values(): IterableIterator>; toRecord(): Record; /** Build packed prefix candidates before a latency-sensitive targeted-pull phase. */ preparePrefixIndex(): JournalPrefixIndex; /** * Returns and clears changes since the prior checkpoint. * * A non-tracking store has no change stream; asking it to drain is a caller * error rather than an empty checkpoint. */ drainDirtyLog(): JournalRowChange[]; /** Read pending changes without acknowledging them; writeJournal snapshots before append. */ dirtyLogSnapshot(): readonly JournalRowChange[]; /** Alias for callers that treat the dirty log as a change stream. */ drainChanges(): JournalRowChange[]; /** * Rewrites active rows densely. Checkpoints drain the dirty log first, so * row ids in already-emitted records remain meaningful. */ compact(): void; /** * Export a hole-free immutable view for the HQSNAP4 encoder. Snapshot * publication is already a compaction boundary, but this keeps the encoder * correct when a future caller invokes it before that boundary. */ toSnapshot(): JournalRowStoreSnapshot; /** * Renumber sparse rows directly in their packed columns for snapshot output. * A delete leaves an in-memory hole so row ids held by the dirty log remain * stable; a durable snapshot cannot carry that hole because its row count is * the number of live rows. Keep this conversion columnar: materialising every * path/entry pair here would defeat HQSNAP4's resident-store write path. */ private denseSnapshotWithoutMaterializingRows; private copyDenseStringEntry; /** Install the already-authenticated HQSNAP4 column views without row parsing. */ static fromSnapshot(snapshot: JournalRowStoreSnapshot): JournalRowStore; private reset; private insertWithoutDirtyLog; private addRowToPrefixIndex; private removeRowFromPrefixIndex; private ensurePrefixId; private addDynamicPrefixRow; private removeDynamicPrefixRow; private prefixesForPath; private recordDirty; private allocateRow; private ensureRowCapacity; private writeEntry; private clearRow; private propertyOrderIdFor; private appendIterationRow; private removeIterationRow; private materialize; private internDirectory; private internAuthor; private appendLeaf; private storeLeafFallback; private leafBytes; private pathForRow; private pathForRowForPrefixIndex; private findRowId; private findIndexedRow; private ensureBucketCapacity; private rehash; private insertIndex; private deleteIndex; private hashBytes; } /** A descriptive alias for call sites that prefer the design document's name. */ export { JournalRowStore as PackedJournalRowStore }; //# sourceMappingURL=journal-row-store.d.ts.map