diff --git a/docs/INDEX_PROVENANCE.md b/docs/INDEX_PROVENANCE.md index 38067f4..808f281 100644 --- a/docs/INDEX_PROVENANCE.md +++ b/docs/INDEX_PROVENANCE.md @@ -50,7 +50,7 @@ loading. The lockstep `ordvec-manifest` crate provides a sidecar verifier for that pre-load step: ```sh -cargo run -p ordvec-manifest --features cli -- verify --manifest path/to/index.manifest.json +cargo run -p ordvec-manifest -- verify --manifest path/to/index.manifest.json ``` The `create` command emits default-verifiable manifests by default: artifact diff --git a/docs/msrv-and-features.md b/docs/msrv-and-features.md index 02dfa48..2302212 100644 --- a/docs/msrv-and-features.md +++ b/docs/msrv-and-features.md @@ -9,9 +9,9 @@ target inventory lives in [artifact-platform-matrix.md](artifact-platform-matrix Current MSRV: Rust 1.89. The MSRV applies to all Rust crates in this repository: `ordvec`, -`ordvec-manifest`, `ordvec-python`, `ordvec-manifest-python`, and -`ordvec-ffi`. The CI MSRV job, each `Cargo.toml` `rust-version`, and the -README MSRV badge/section must stay synchronized. Raising the MSRV is a +`ordvec-manifest`, `ordvec-python`, `ordvec-manifest-python`, `ordvec-ffi`, and +the standalone `ordvec-fuzz` crate. The CI MSRV job, each `Cargo.toml` `rust-version`, +and the README MSRV badge/section must stay synchronized. Raising the MSRV is a minor-version compatibility change and release notes must state the reason and any migration note. @@ -20,7 +20,7 @@ any migration note. | Surface | Default features | Stable default-off features | Optional dependency features | Experimental/internal features | | --- | --- | --- | --- | --- | | `ordvec` | none | `serde` derives `Serialize`/`Deserialize` for `SearchResults` only | `serde` | `experimental` exposes `MultiBucketBitmap`; `test-utils` is repo-test-only and has no public stability promise. | -| `ordvec-manifest` | none | none | `cli`, `sqlite`, `sqlite-bundled` | none | +| `ordvec-manifest` | `cli` | none | `cli`, `sqlite`, `sqlite-bundled` | none | | `ordvec-python` | n/a | n/a | n/a | n/a | | `ordvec-manifest-python` | n/a | n/a | n/a | n/a | | `ordvec-ffi` | none | none | none | none | @@ -31,10 +31,11 @@ built with that target feature, and other targets use the scalar fallback. Host systems should not need BLAS, LAPACK, `ndarray`, `faer`, or a native graph library to embed the core crate. -`ordvec-manifest` keeps its library default feature set empty. The `cli` -feature enables the `ordvec-manifest` binary and its `clap` dependency. The -`sqlite` feature enables the local cache/audit subcommands; `sqlite-bundled` -adds the bundled SQLite build through `rusqlite`. +`ordvec-manifest` enables `cli` by default so `cargo install +ordvec-manifest` installs the command-line utility without extra flags. Library +consumers that do not need the CLI can use `default-features = false` to avoid +the `clap` dependency. The `sqlite` feature enables the local cache/audit +subcommands; `sqlite-bundled` adds the bundled SQLite build through `rusqlite`. ## Change Policy diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index ae82c79..0a4b787 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -3,6 +3,7 @@ name = "ordvec-fuzz" version = "0.0.0" publish = false edition = "2021" +rust-version = "1.89" [package.metadata] cargo-fuzz = true diff --git a/ordvec-manifest/Cargo.toml b/ordvec-manifest/Cargo.toml index cfe9eb2..b00029a 100644 --- a/ordvec-manifest/Cargo.toml +++ b/ordvec-manifest/Cargo.toml @@ -14,6 +14,7 @@ categories = ["algorithms", "command-line-utilities", "data-structures"] [package.metadata.docs.rs] all-features = false +features = ["cli", "sqlite-bundled"] [lib] name = "ordvec_manifest" @@ -39,7 +40,7 @@ uuid = { version = "1.23.2", features = ["v4"] } tempfile = "3.27.0" [features] -default = [] +default = ["cli"] cli = ["dep:clap"] sqlite = ["dep:rusqlite"] sqlite-bundled = ["sqlite", "rusqlite/bundled"] diff --git a/ordvec-manifest/README.md b/ordvec-manifest/README.md index e60e002..1e3952b 100644 --- a/ordvec-manifest/README.md +++ b/ordvec-manifest/README.md @@ -11,10 +11,10 @@ index files, decide deployment trust policy, estimate encoder geometry, compute calibration statistics, or change the C ABI. `ordvec-manifest` is versioned in lockstep with the core `ordvec` crate. From a -workspace checkout, use the optional CLI with -`cargo run -p ordvec-manifest --features cli --`; from a published release, -install the binary with `cargo install ordvec-manifest --features cli`. The -library default feature set is empty and does not depend on `clap`. +published release, install the binary with `cargo install ordvec-manifest`. +From a workspace checkout, use the CLI with `cargo run -p ordvec-manifest --`. +Library-only consumers that do not need the CLI can depend on the crate with +`default-features = false`. ```sh ordvec-manifest create \ @@ -28,7 +28,7 @@ ordvec-manifest verify --manifest path/to/index.manifest.json ``` From a workspace checkout, prefix the same commands with -`cargo run -p ordvec-manifest --features cli --`. +`cargo run -p ordvec-manifest --`. The schema version is `ordvec.index_manifest.v1`. Relative paths resolve from the manifest file's directory, absolute paths are rejected by default, and @@ -94,14 +94,14 @@ fn write_bundle( Then create and verify a manifest that binds both files: ```sh -cargo run -p ordvec-manifest --features cli -- create \ +cargo run -p ordvec-manifest -- create \ --index docs.odb/index.ovrq \ --row-id-is-identity \ --aux app.ids=docs.odb/ids.bin \ --embedding-model bge-small-en-v1.5 \ --out docs.odb/manifest.json -cargo run -p ordvec-manifest --features cli -- verify \ +cargo run -p ordvec-manifest -- verify \ --manifest docs.odb/manifest.json \ --json ``` diff --git a/tests/release_publish_invariants.py b/tests/release_publish_invariants.py index 4bf2637..bed9669 100644 --- a/tests/release_publish_invariants.py +++ b/tests/release_publish_invariants.py @@ -455,6 +455,10 @@ def check_release_compatibility_sync() -> None: if rust_version != core_msrv: fail(f"{path}: package.rust-version is {rust_version}, expected {core_msrv}") + fuzz_rust_version = package_rust_version("fuzz/Cargo.toml") + if fuzz_rust_version != core_msrv: + fail(f"fuzz/Cargo.toml: package.rust-version is {fuzz_rust_version}, expected {core_msrv}") + readme = read_text("README.md") minor_req = semver_minor_requirement(core_version) quickstart = re.search(r"(?ms)^## Quickstart\b.*?```toml\n(?P.*?)\n```", readme) @@ -532,6 +536,42 @@ def check_registry_metadata_parity() -> None: docs_rs = mapping(docs.get("rs"), f"{path}: package.metadata.docs.rs") if docs_rs.get("all-features") is not False: fail(f"{path}: package.metadata.docs.rs.all-features must be false") + if path == "ordvec-manifest/Cargo.toml": + features = string_sequence( + docs_rs.get("features"), f"{path}: package.metadata.docs.rs.features" + ) + if features != ["cli", "sqlite-bundled"]: + fail( + f"{path}: package.metadata.docs.rs.features is {features!r}, " + "expected ['cli', 'sqlite-bundled']" + ) + elif "features" in docs_rs: + fail(f"{path}: package.metadata.docs.rs.features must not be set") + + +def check_manifest_cli_defaults() -> None: + manifest = load_toml("ordvec-manifest/Cargo.toml") + features = mapping(manifest.get("features"), "ordvec-manifest/Cargo.toml: features") + default_features = string_sequence( + features.get("default"), "ordvec-manifest/Cargo.toml: features.default" + ) + if default_features != ["cli"]: + fail("ordvec-manifest/Cargo.toml: default features must be ['cli']") + cli_features = string_sequence( + features.get("cli"), "ordvec-manifest/Cargo.toml: features.cli" + ) + if "dep:clap" not in cli_features: + fail("ordvec-manifest/Cargo.toml: features.cli must enable dep:clap") + + text = read_text("ordvec-manifest/Cargo.toml") + if 'name = "ordvec-manifest"' not in text or 'required-features = ["cli"]' not in text: + fail("ordvec-manifest/Cargo.toml: binary must remain gated on the cli feature") + + readme = read_text("ordvec-manifest/README.md") + if "cargo install ordvec-manifest --features cli" in readme: + fail("ordvec-manifest/README.md: install instructions must not require --features cli") + if "cargo install ordvec-manifest" not in readme: + fail("ordvec-manifest/README.md: must document default cargo install") def check_publication_model() -> None: @@ -1933,6 +1973,7 @@ def main() -> None: check_release_version_sync() check_release_compatibility_sync() check_registry_metadata_parity() + check_manifest_cli_defaults() check_publication_model() check_python_package_metadata() check_release_docs_include_manifest_pypi_lane()