Skip to content

Define and enforce the 1.x compatibility contract - #29

Merged
tvanreenen merged 10 commits into
mainfrom
public-contract-0.7.0
Aug 24, 2026
Merged

Define and enforce the 1.x compatibility contract#29
tvanreenen merged 10 commits into
mainfrom
public-contract-0.7.0

Conversation

@tvanreenen

@tvanreenen tvanreenen commented Aug 24, 2026

Copy link
Copy Markdown
Owner

Overview

NumPy Vector Store is close enough to 1.0 that users need to know which parts of the library they can safely build against, and maintainers need release checks that enforce those promises. This PR defines the intended 1.x compatibility contract and adds the repository-owned safeguards needed to publish that contract with confidence during the 0.7 adoption cycle.

This remains a hardening change. It does not add a new feature family, remove an API, change search results, or introduce a new archive format.

What changes

  • Declares VectorStore, VectorHit, and __version__ as the supported top-level package exports and tests that declaration.
  • Adds an accessible compatibility policy covering the supported API, ownership behavior, exception classes, VectorHit comparison behavior, deprecation rules, Python and NumPy support, performance expectations, and format-version-1 archive guarantees.
  • Modernizes distribution metadata with the SPDX MIT license expression, explicit license-file inclusion, the Typing :: Typed classifier, and Beta maturity for the 0.7 adoption cycle.
  • Adds a dependency-free publication check that compares the source version, GitHub release tag, wheel metadata, and source-distribution metadata before either artifact can be uploaded to PyPI.
  • Requires an unambiguous build directory containing exactly one wheel and one source distribution, preventing stale artifacts from being published alongside the intended release.
  • Pins every remote GitHub Action to an immutable full commit SHA while retaining readable version comments for future maintenance.
  • Runs the complete test suite on Windows in addition to the supported Python matrix on Linux.
  • Makes filesystem tests follow the documented cross-platform contract by accepting the platform's relevant OSError subclass and checking exact POSIX permission preservation only where the filesystem can represent those bits.
  • Covers the remaining malformed format-version-1 archive boundaries: unexpected fields, nonpositive persisted dimensions, one-dimensional vector storage, and multidimensional metadata storage.

Why this helps

Before this change, the package documentation described behavior in several places but did not draw one clear line between supported API and implementation detail. That makes normal maintenance riskier: users may reasonably depend on a submodule path, private helper, exact error message, or incidental VectorHit behavior without knowing that it was never intended as a stable interface.

The new policy makes the small supported surface easy to find and explains what stability will mean after 1.0. It also protects the persistence promise users care about: every 1.x release will continue to read and write valid format-version-1 archives, while pickle-backed metadata remains explicitly limited to trusted files with compatible application types available.

The publication checks address a different but related risk. A release can pass ordinary tests and still be mislabeled if the GitHub tag, source version, or built metadata is stale. Comparing the values inside the actual wheel and source distribution stops that class of mistake before trusted publishing starts.

User impact

Existing valid applications do not need to change. The constructor, search methods, result values, row ownership, persistence lifecycle, Python and NumPy requirements, and archive format remain unchanged.

Users gain a documented top-level import contract, a concrete 1.x compatibility policy, clearer installation and optional-row examples, correctly declared typing and licensing metadata, cross-platform test evidence, and stronger assurance that the version downloaded from PyPI matches the release they selected.

Code importing from numpy_vector_store.vector_store, subclassing VectorStore, or depending on private state continues to work where it works today, but the compatibility document now makes clear that those are not supported extension points. No runtime warning or forced migration is introduced.

Implementation details

The release verifier uses only the Python standard library. It parses the literal __version__ assignment from the source file, reads Version from the wheel's .dist-info/METADATA, reads Version from the source distribution's PKG-INFO, and optionally compares the v<version> GitHub release tag. TestPyPI keeps the same artifact checks without requiring a release tag because that workflow is manually dispatched.

The Windows job intentionally runs the full suite instead of selecting persistence tests by name. The project is small enough that this remains inexpensive, and the broader run also catches platform-specific path, temporary-file, NumPy, and filesystem behavior without adding wall-clock performance thresholds.

Remote actions use immutable commits because tags and branches can move. The adjacent release comments preserve the human-readable versions so future dependency updates remain straightforward.

Documentation and ancillary changes

  • Adds COMPATIBILITY.md and links it from the README and roadmap.
  • Adds a standard pip installation command alongside the existing uv example.
  • Updates get() examples to handle its documented optional return before unpacking.
  • Replaces an overly broad portability claim with precise single-file archive wording.
  • Corrects the 0.6.0 changelog date from August 21 to its actual August 22 publication date.
  • Updates the 0.7 roadmap from planned language to the concrete contract and safeguards delivered here.

Verification

  • uv lock --check
  • uv run --locked ruff check .
  • uv run --locked ruff format --check .
  • uv run --locked mypy src/ benchmarks/ tools/
  • 340 tests passed on Python 3.13 with warnings treated as errors and 99% package-source coverage.
  • 340 tests passed on Python 3.11 with the minimum supported NumPy 1.23.2 and warnings treated as errors.
  • A fresh wheel and source distribution passed the new source/tag/artifact version check using v0.6.0, the current source version on this pre-release branch.
  • The same fresh artifacts passed twine check; both include the MIT license, and the wheel includes py.typed.
  • All seven GitHub Actions checks passed: Python 3.11, 3.12, 3.13, and 3.14 on Linux, the minimum NumPy boundary on Python 3.11, lint/format/type checking, and the full suite on Windows with Python 3.13.

Release and migration notes

This PR deliberately leaves __version__ at 0.6.0. The separate 0.7.0 release-preparation PR will update the version, write the final changelog entry, mark the milestone complete, and validate clean installation before tagging.

No data migration is required. The archive schema remains format version 1, and this change adds no runtime dependency.

The PyPI job retains its existing least-privilege OIDC permissions. This PR does not add a named GitHub deployment environment because that name must be coordinated with the external PyPI Trusted Publisher configuration; adding one unilaterally could block publication rather than protect it.

@tvanreenen tvanreenen self-assigned this Aug 24, 2026
@tvanreenen tvanreenen changed the title Define the public 1.x compatibility contract Define and enforce the 1.x compatibility contract Aug 24, 2026
@tvanreenen
tvanreenen marked this pull request as ready for review August 24, 2026 15:36
@tvanreenen
tvanreenen merged commit 2993be1 into main Aug 24, 2026
7 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