Skip to content

Prepare NumPy Vector Store 0.6.0 for release - #25

Merged
tvanreenen merged 3 commits into
mainfrom
prepare-release-0.6.0
Aug 22, 2026
Merged

Prepare NumPy Vector Store 0.6.0 for release#25
tvanreenen merged 3 commits into
mainfrom
prepare-release-0.6.0

Conversation

@tvanreenen

Copy link
Copy Markdown
Owner

What this PR does

This PR prepares NumPy Vector Store 0.6.0 for release after the four implementation PRs in the milestone. It sets the package version, adds a complete release narrative, marks the roadmap milestone complete, and updates the README so its compatibility and benchmark provenance describe the code that will actually ship.

The release itself is about predictable contracts rather than a new feature family. It makes scalar inputs explicit, validates search preconditions consistently regardless of store size, clarifies persistence path and failure behavior, protects format-version-1 compatibility with a real published archive, and replaces informal performance claims with reproducible evidence.

Why this release matters

Before 0.6, some invalid calls were accepted through Python or NumPy side effects. A boolean could behave like an integer count or row index, malformed search filters could be skipped when a store was empty, and configuration accepted through truth-value coercion could change meaning after a save/open round trip. Those cases made behavior depend on incidental implementation details rather than the public API.

Version 0.6 establishes one understandable rule at the boundary: supported values are converted to a canonical form, inappropriate types raise TypeError, supported types with invalid values raise ValueError, and row selector bounds raise IndexError. Exact message text remains explanatory rather than becoming a compatibility promise.

This is also the point where the project can state its intended scale more honestly. NumPy Vector Store remains a small-to-medium, in-process exact-search tool. The README stops its aligned benchmark grid at 100,000 rows and explains why routinely million-row workloads generally need an indexed or service-backed system.

Release contents

Predictable public inputs

  • dimensions, top_k, and get(index) accept integer-index values and reject Python and NumPy booleans.
  • normalize accepts Python and NumPy booleans and retains a canonical Python bool.
  • Search thresholds accept finite real Python and NumPy scalars while rejecting booleans, strings, complex values, arrays, and non-finite values.
  • within_rows is always checked for one-dimensional shape, integer values, uniqueness, and bounds, including on an empty store.
  • Metric-specific zero-query rules now apply before empty-result shortcuts: cosine always requires a non-zero query; normalized dot and Euclidean search do as well; raw dot and Euclidean search continue accepting one.

Persistence contracts

  • Persistence accepts strings and string-returning path-like objects, rejects explicit empty paths, and keeps omitted save() paths distinct from save("").
  • Filesystem, schema, NumPy, pickle, and application metadata failures retain their owning exception boundaries instead of being flattened into a package-specific wrapper.
  • A fixture produced by the published 0.4.0 package on Python 3.11 and NumPy 1.23.2 protects forward reading of self-describing format-version-1 archives.
  • Archive format version 1 is unchanged. This does not restore the unversioned reader or removed 0.4 APIs, and no archive conversion is required when upgrading from 0.5.

Reproducible performance evidence

  • Repository benchmark commands now emit workload details, input digests, raw samples, medians, Git state, runtime versions, timer information, thread settings, and NumPy build configuration as JSON.
  • Structural tests protect geometric ingestion capacity, partial top-k selection, and unfiltered search without a preliminary full-matrix copy; shared CI intentionally avoids machine-specific wall-clock thresholds.
  • The complete README benchmark grid was rerun against permanent clean squash commit 4b23810 on a 24 GB Apple M4 Mac mini. The documented cosine-search range is about 0.032 ms per query at 1,000 rows × 384 dimensions through 20.509 ms at 100,000 rows × 3,072 dimensions.
  • The 100,000-row × 3,072-dimension matrix alone uses about 1.23 GB, making the memory and scope boundary visible alongside latency.

Release documentation and metadata

  • Set the package version to 0.6.0.
  • Add detailed changelog sections covering the API shape, rationale, user-visible changes, persistence boundary, benchmark design, runtime support, and upgrade review points.
  • Mark the 0.6.0 roadmap milestone complete and extend the documented Python 3.11–3.14 support policy through this release.
  • Update the README's current-reader wording from 0.5 to 0.6 and replace pre-squash benchmark provenance with the stable main commit and its measurements.

User impact and upgrade guidance

Valid, documented 0.5 usage should continue unchanged. The release adds no public class, runtime dependency, exception hierarchy, metadata query language, archive format, or persistence migration.

Applications should review call sites that pass booleans where integer counts or indexes are expected, fractional top_k values, string or boolean thresholds, duplicate or malformed within_rows values, zero queries that were only attempted against empty stores, or explicitly empty persistence paths. Those accidentally accepted or state-dependent inputs now fail consistently at the public boundary.

Python 3.11 through 3.14 and NumPy 1.23.2 or newer remain supported. Python 3.10 remains supported by the 0.3 release series, not by 0.4 or later.

Verification

  • uv lock --check
  • ruff check .
  • ruff format --check .
  • mypy src/ benchmarks/
  • 298 tests passed with warnings treated as errors on Python 3.13.5, with 98% source coverage.
  • The same 298 tests passed with warnings treated as errors on Python 3.11.13 and the minimum supported NumPy 1.23.2.
  • Clean 0.6.0 source and wheel distributions built successfully, and Twine accepted both artifacts.
  • The source distribution contains the benchmark command and guide, regression tests, and published-0.4 compatibility fixture; the wheel remains limited to runtime package files.
  • A clean Python 3.11 install from the built wheel passed version, search, save, and open smoke checks.
  • The official PyPI version endpoint, Git tag endpoint, and GitHub release endpoint all confirmed that 0.6.0 does not already exist before this PR.

Release notes

This PR does not create a tag or publish a package. After it is squash merged, v0.6.0 should be attached to the exact resulting main commit and published as a GitHub release. The existing release workflow will rerun the supported checks and publish the distributions to PyPI through trusted publishing.

@tvanreenen tvanreenen self-assigned this Aug 21, 2026
@tvanreenen
tvanreenen marked this pull request as ready for review August 22, 2026 06:19
@tvanreenen
tvanreenen merged commit 5c6ad40 into main Aug 22, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant