Releases: HarperFast/hnsw
Release list
v0.2.1
Fixes the local-minimum descent bug that blocked v0.2.0 (see 294d465): the upper-layer descent now beams at width 16 instead of greedy width 1, so a query can no longer be stranded in the wrong basin. v0.2.0 is superseded and should not be installed.
v0.2.0
First release to ship prebuilt bindings. Installing @harperfast/hnsw now resolves a platform package (darwin-arm64, linux-x64-glibc, linux-arm64-glibc, win32-x64) and only falls back to a local Rust build when none matches (musl, or any other target).
Brings the crate up to the reviewed native delta of HarperFast/harper#2430 and adds a package-owned, durable way to invalidate a plane file the host cannot delete, so Harper can replace its vendored native/hnsw-plane with the released package.
Plane invalidation (new)
invalidatePlane(path) / invalidatePlaneAsync(path), and plane.invalidateFile() through a handle already held. A plane the host cannot unlink — a Windows sharing violation while another process maps it — must never be adopted later at its nonzero watermark, so invalidation is a one-way latch rather than a mutable tombstone: a flushAsync already in flight can still stamp the watermark word but cannot revive the plane.
- Two markers, both attempted on every call, in band first: a sticky header byte under which
getWatermark()reads 0 on every handle, plus a.stalesidecar created with create-new semantics and fsync'd along with its directory entry on POSIX. The call throws only when neither marker is durable, leaving the file exactly as found. - Enforced by the package:
open()refuses a file carrying either marker (fail-closed — any directory entry at the sidecar name counts), andcreate()refuses a path with a leftover sidecar. An existing sidecar is re-synced through a no-follow, non-blocking open validated on the handle, so a planted symlink or FIFO is refused rather than followed. invalidated()is the diagnostic that reports why a plane reads as empty.
Graph changes
- First-insert claim/join, so concurrent first inserts cannot orphan each other.
- Search-side entry repair with a rotating bounded probe, now with a futility latch: a fully dead graph stops probing after one empty rotation and re-arms on any node write through any handle, keyed on a header write epoch, instead of paying 1024 node reads per search forever.
- A stale re-election can no longer CAS over an equal-level entry a fresh first-insert claim just installed.
- Insert deletes the edgeless node it published when its bounded entry resolution falls out wedged.
- Predicate-drain fixes.
Format
Format v7 — existing plane files are not readable and must be reindexed. The neighbor and upper-id arrays are 4-aligned (v6) and the invalidation latch byte is defined (v7). There is no read-only tolerance of v5/v6 files; 0.1.0 shipped without a consumer, so no migration path was built.
Full detail, including the reviewer-facing trade-offs, in #1.