/** * Content-Addressable Hashing for incremental reindex (Phase 2). * * A 64-bit xxHash over file contents lets the indexer skip re-parsing when * `touch` or `git checkout` rewrites `mtime_ms` without changing actual bytes. * The corresponding SQLite column `files.content_hash` is added by Phase 2 to * the existing `files` table; see `writer-schema.ts`. * * Why xxHash64 and not SHA-256 / BLAKE3 / crypto: * * - Non-cryptographic — we're not authenticating anything, just fingerprinting. * - 64-bit output — collision probability for a million files is ~1e-13, * which is well below the indexer error budget. SHA-256 is overkill. * - Constant-time on small inputs — the inner loop is a few ALU ops per * byte, no allocations after the initial seed. * - Zero dependency — keeps `packages/tools` slim. The alternative * (`hash-wasm`, `blake3-wasm`) would add ~150 KB to the bundle for a * function we call once per file. * - Deterministic across runs and platforms — the canonical xxHash64 * reference implementation is byte-identical regardless of endianness. * * Algorithm: Yann Collet's xxHash64 (BSD-2-Clause), seed `0`. The constants * and round/merge functions are reproduced from the xxhash spec at * https://github.com/Cyan4973/xxHash/blob/dev/doc/xxhash_spec.md — any * change here must be validated against the KAT vectors in * `codebase-index-content-hash.test.ts`, or two different installs of * WrongStack will report different hashes for the same file and trigger * spurious re-indexing. * * Spec notations: * - `<<<` = rotate-left (circular shift), NOT logical shift * - `*` = modular multiplication mod 2^64 (full 64x64 -> 64) * - All multi-byte reads are little-endian */ /** * Compute xxHash64 of `buf` with seed `0`. Returns a 16-character lowercase * hex string. * * The string format is what gets stored in `files.content_hash`. Keeping it * hex (vs. raw BigInt) means the SQLite column can be a plain TEXT and is * debuggable from the `sqlite3` CLI without bespoke formatters. */ export declare function xxhash64Hex(buf: Uint8Array, explicitLen?: number): string; /** * Convenience wrapper: hash a UTF-8 string. The indexer feeds file contents * as `string` (Node.js convention) rather than `Buffer`, so this is the * common entry point. * * Note: the buffer capacity does NOT participate in the hash — only the * bytes up to `content.length` do. The caller is responsible for passing a * `Uint8Array` whose `.length` is the byte count of the content. */ export declare function xxhash64String(content: string): string; /** * Parse a stored `content_hash` value (from SQLite) and return the * equivalent BigInt, or `undefined` for empty / unknown values. * * Used by the indexer's incremental path: when both the stored and the fresh * hash parse cleanly, they're compared as 64-bit integers in O(1) without * string allocation. The hex-string storage format is the on-disk contract; * this function is the in-memory helper. */ export declare function parseContentHash(value: string | null | undefined): bigint | undefined; //# sourceMappingURL=content-hash.d.ts.map