Uh oh!
There was an error while loading. Please reload this page.
chore(deps): bump actions/github-script from 7 to 9 - #3
Conversation
|
dcb0a81 to
1914830Compareajianaz
commented
Aug 28, 2026
@dependabot rebase |
Looks like this PR is already up-to-date with develop! If you'd still like to recreate it from scratch, overwriting any edits, you can request |
🔍 Cora AI Code ReviewReview powered by cora-code · BYOK · MIT |
ajianaz
commented
Aug 28, 2026
@dependabot rebase |
Bumps [actions/github-script](https://github.com/actions/github-script) from 7 to 9. - [Release notes](https://github.com/actions/github-script/releases) - [Commits](actions/github-script@v7...v9) --- updated-dependencies: - dependency-name: actions/github-script dependency-version: '9' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
1914830 to
9160b7bCompareajianaz
commented
Aug 28, 2026
Merge-gate triage: Cora Review MAJOR finding ( |
Uh oh!
There was an error while loading. Please reload this page.
* chore(cora): raise review llm max_tokens to 16384 glm-5.3 is a reasoning model; on dependency-lockfile diffs the default 4096-token budget is exhausted during reasoning (finish_reason=length, content=null), which made the CI cora-review fallback SARIF fire on PRs #2/#3. 16384 leaves room for reasoning plus the verdict. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> * chore: retrigger CI Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> --------- Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com>
* chore: align .cora.yaml with current cora schema (#4) * chore: align .cora.yaml with current cora schema The old file used `review.enabled`, which the current cora binary rejects (unknown field), silently disabling pre-commit review. Mirrors the uteke .cora.yaml structure with vecq-specific rules (determinism, zero-dependency core). * fix: gate NEON-only bindings behind cfg(aarch64) bpv and q_rot are only used on the NEON path; on x86_64 builds they were unused variables, failing clippy -D warnings in CI. * fix: restore bpv under cfg(aarch64), verify local clippy clean * fix: gate NEON test bindings behind cfg(aarch64) for x86_64 builds * fix: cfg-gate remaining NEON test bindings * fix: cfg-gate the NEON parity test at function level --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * ci: add release workflow (crates.io publish via tag) (#6) * chore: align .cora.yaml with current cora schema (#4) (#5) * chore: align .cora.yaml with current cora schema The old file used `review.enabled`, which the current cora binary rejects (unknown field), silently disabling pre-commit review. Mirrors the uteke .cora.yaml structure with vecq-specific rules (determinism, zero-dependency core). * fix: gate NEON-only bindings behind cfg(aarch64) bpv and q_rot are only used on the NEON path; on x86_64 builds they were unused variables, failing clippy -D warnings in CI. * fix: restore bpv under cfg(aarch64), verify local clippy clean * fix: gate NEON test bindings behind cfg(aarch64) for x86_64 builds * fix: cfg-gate remaining NEON test bindings * fix: cfg-gate the NEON parity test at function level --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * ci: add release workflow (crates.io publish via tag, uteke pattern) --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * chore: bump version to 0.1.1 (#8) * chore: align .cora.yaml with current cora schema (#4) (#5) * chore: align .cora.yaml with current cora schema The old file used `review.enabled`, which the current cora binary rejects (unknown field), silently disabling pre-commit review. Mirrors the uteke .cora.yaml structure with vecq-specific rules (determinism, zero-dependency core). * fix: gate NEON-only bindings behind cfg(aarch64) bpv and q_rot are only used on the NEON path; on x86_64 builds they were unused variables, failing clippy -D warnings in CI. * fix: restore bpv under cfg(aarch64), verify local clippy clean * fix: gate NEON test bindings behind cfg(aarch64) for x86_64 builds * fix: cfg-gate remaining NEON test bindings * fix: cfg-gate the NEON parity test at function level --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * release: v0.1.1 crates.io publish pipeline (#7) * chore: align .cora.yaml with current cora schema (#4) * chore: align .cora.yaml with current cora schema The old file used `review.enabled`, which the current cora binary rejects (unknown field), silently disabling pre-commit review. Mirrors the uteke .cora.yaml structure with vecq-specific rules (determinism, zero-dependency core). * fix: gate NEON-only bindings behind cfg(aarch64) bpv and q_rot are only used on the NEON path; on x86_64 builds they were unused variables, failing clippy -D warnings in CI. * fix: restore bpv under cfg(aarch64), verify local clippy clean * fix: gate NEON test bindings behind cfg(aarch64) for x86_64 builds * fix: cfg-gate remaining NEON test bindings * fix: cfg-gate the NEON parity test at function level --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * ci: add release workflow (crates.io publish via tag) (#6) * chore: align .cora.yaml with current cora schema (#4) (#5) * chore: align .cora.yaml with current cora schema The old file used `review.enabled`, which the current cora binary rejects (unknown field), silently disabling pre-commit review. Mirrors the uteke .cora.yaml structure with vecq-specific rules (determinism, zero-dependency core). * fix: gate NEON-only bindings behind cfg(aarch64) bpv and q_rot are only used on the NEON path; on x86_64 builds they were unused variables, failing clippy -D warnings in CI. * fix: restore bpv under cfg(aarch64), verify local clippy clean * fix: gate NEON test bindings behind cfg(aarch64) for x86_64 builds * fix: cfg-gate remaining NEON test bindings * fix: cfg-gate the NEON parity test at function level --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * ci: add release workflow (crates.io publish via tag, uteke pattern) --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * chore: bump version to 0.1.1 for first crates.io release --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * ci: add cora AI code review workflow (parity with uteke) (#13) * ci: add cora AI code review workflow (parity with uteke) Runs codecoradev/cora-review-action@v1 on every PR targeting develop or main, posting AI review feedback using org CORA_* secrets, matching the uteke repo reference workflow. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> * chore: retrigger CI to verify cora review secrets Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> --------- Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * fix(ci): correct CLA bot exemption to match actual bot logins (#14) dependabot PR authors have user.login `dependabot[bot]`, not `app/dependabot`, so the old skip list never matched and the CLA job failed every dependabot PR. Switch to an exact allowlist of trusted bot logins (dependabot/renovate/github-actions); the legacy app/* forms stay as fallbacks. A substring [bot] match was rejected in review — it would exempt arbitrary third-party GitHub Apps. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * chore(deps): bump rand from 0.8.8 to 0.10.2 (#2) Bumps [rand](https://github.com/rust-random/rand) from 0.8.8 to 0.10.2. - [Release notes](https://github.com/rust-random/rand/releases) - [Changelog](https://github.com/rust-random/rand/blob/master/CHANGELOG.md) - [Commits](rust-random/rand@0.8.8...0.10.2) --- updated-dependencies: - dependency-name: rand dependency-version: 0.10.2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump actions/github-script from 7 to 9 (#3) Bumps [actions/github-script](https://github.com/actions/github-script) from 7 to 9. - [Release notes](https://github.com/actions/github-script/releases) - [Commits](actions/github-script@v7...v9) --- updated-dependencies: - dependency-name: actions/github-script dependency-version: '9' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(cora): raise review llm max_tokens to 16384 (#15) * chore(cora): raise review llm max_tokens to 16384 glm-5.3 is a reasoning model; on dependency-lockfile diffs the default 4096-token budget is exhausted during reasoning (finish_reason=length, content=null), which made the CI cora-review fallback SARIF fire on PRs #2/#3. 16384 leaves room for reasoning plus the verdict. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> * chore: retrigger CI Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> --------- Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * feat(core): keyed API — add_keyed/remove_keyed/tombstones (#10) (#16) Adds the keyed layer requested for incremental integrators (issue #10, unblocks the cora-code adoption audit): - add_keyed(key, v): insert-or-replace under a stable u64 key (usearch-style), returns the slot index - remove_keyed(key) -> bool: tombstones the slot; storage stays in place so slot indices remain stable until compact() - search_keyed(q, k): top-k by key, tombstones skipped - compact(): rebuilds in place, dropping tombstones (keys preserved, slot indices shift) - key_of/contains_key/slots/tombstones introspection helpers - len()/is_empty() now report live vectors - to_bytes() writes live slots only: tombstones are dropped on disk without disturbing in-memory slot indices. File format unchanged (v1.1); keys are an in-memory concern — persist key->slot mappings in your own metadata store. NEON4 batch scoring is untouched: tombstoned slots are still scored to keep batches dense, then filtered before entering the top-k heap, preserving bit-identical results. TDD: 7 new tests cover keyed search, replace, stability across remove/serialize, compaction, drained indexes, keyed adds after a file load, and dim-mismatch panics. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * feat(core): x86_64 AVX2 scoring path (parity with NEON, bit-identity tested) (#17) * feat(core): x86_64 AVX2 scoring path, bit-identical to scalar (#11) Adds an explicit AVX2 nibble-gather scoring path mirroring the NEON one, selected at runtime with is_x86_feature_detected! (AVX2 is not baseline on x86_64): - score_avx2: 8 lanes = 8 scalar buckets; per 8-byte block, lane j computes q[2b]*lut[lo_b] + q[2b+1]*lut[hi_b] (mul, mul, add — no FMA) and accumulates in block order, then the same pairwise-tree reduction — structurally identical to the scalar loop, so results are bit-identical - score_avx24: 4-vector batch sharing the q deinterleave - LUT gather via vgatherdps (scale 4, nibble indices); q even/odd deinterleave via shuffle_ps + vpermps fixup - search() dispatches to the AVX2 batch when available; score() dispatches per call Bit-identity is enforced by new tests (avx2_matches_scalar_bitwise, avx24_matches_avx2_bitwise, search dispatch == scalar) including a dim-8 case covering the 4-byte tail. The x86_64 CI job runs these on native AVX2 hardware (Rosetta hides AVX2 via CPUID, so local emulated runs cannot exercise the path). docs/BENCHMARK.md: per-architecture scoring-path table; x86_64 numbers explicitly pending native measurement, Rosetta excluded. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> * fix(clippy): iterate acc via enumerate in score_avx24 batch loop clippy 1.98 (CI stable) flags the 0..4 indexing loop under needless_range_loop; local 1.89 does not. Same semantics. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> --------- Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * docs: canonical SQLite BLOB storage pattern (#12) (#18) Adds docs/SQLITE.md: when to embed the index vs standalone file, the single-row and per-shard schema shapes, save/load with rusqlite in one transaction, atomicity notes (WAL + synchronous=NORMAL — no manual checkpoint choreography needed for correctness), measured save/load latencies at 1k/10k/50k vectors (dim 768, ~514 B/vec), and pitfalls (memory duplication on load, slot stability across save/reload interacting with the keyed API, churn-heavy workloads, embed size threshold, seed discipline). README links the page and mentions the per-architecture scoring-path matrix in BENCHMARK.md. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * chore: bump version to 0.2.0 (#19) Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * fix: resolve Cargo.lock conflict markers left from merge The merge committed conflict markers into Cargo.lock; restore the develop-side lock (vecq-core 0.2.0) and verify the workspace builds. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> --------- Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* chore: align .cora.yaml with current cora schema (#4) * chore: align .cora.yaml with current cora schema The old file used `review.enabled`, which the current cora binary rejects (unknown field), silently disabling pre-commit review. Mirrors the uteke .cora.yaml structure with vecq-specific rules (determinism, zero-dependency core). * fix: gate NEON-only bindings behind cfg(aarch64) bpv and q_rot are only used on the NEON path; on x86_64 builds they were unused variables, failing clippy -D warnings in CI. * fix: restore bpv under cfg(aarch64), verify local clippy clean * fix: gate NEON test bindings behind cfg(aarch64) for x86_64 builds * fix: cfg-gate remaining NEON test bindings * fix: cfg-gate the NEON parity test at function level --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * ci: add release workflow (crates.io publish via tag) (#6) * chore: align .cora.yaml with current cora schema (#4) (#5) * chore: align .cora.yaml with current cora schema The old file used `review.enabled`, which the current cora binary rejects (unknown field), silently disabling pre-commit review. Mirrors the uteke .cora.yaml structure with vecq-specific rules (determinism, zero-dependency core). * fix: gate NEON-only bindings behind cfg(aarch64) bpv and q_rot are only used on the NEON path; on x86_64 builds they were unused variables, failing clippy -D warnings in CI. * fix: restore bpv under cfg(aarch64), verify local clippy clean * fix: gate NEON test bindings behind cfg(aarch64) for x86_64 builds * fix: cfg-gate remaining NEON test bindings * fix: cfg-gate the NEON parity test at function level --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * ci: add release workflow (crates.io publish via tag, uteke pattern) --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * chore: bump version to 0.1.1 (#8) * chore: align .cora.yaml with current cora schema (#4) (#5) * chore: align .cora.yaml with current cora schema The old file used `review.enabled`, which the current cora binary rejects (unknown field), silently disabling pre-commit review. Mirrors the uteke .cora.yaml structure with vecq-specific rules (determinism, zero-dependency core). * fix: gate NEON-only bindings behind cfg(aarch64) bpv and q_rot are only used on the NEON path; on x86_64 builds they were unused variables, failing clippy -D warnings in CI. * fix: restore bpv under cfg(aarch64), verify local clippy clean * fix: gate NEON test bindings behind cfg(aarch64) for x86_64 builds * fix: cfg-gate remaining NEON test bindings * fix: cfg-gate the NEON parity test at function level --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * release: v0.1.1 crates.io publish pipeline (#7) * chore: align .cora.yaml with current cora schema (#4) * chore: align .cora.yaml with current cora schema The old file used `review.enabled`, which the current cora binary rejects (unknown field), silently disabling pre-commit review. Mirrors the uteke .cora.yaml structure with vecq-specific rules (determinism, zero-dependency core). * fix: gate NEON-only bindings behind cfg(aarch64) bpv and q_rot are only used on the NEON path; on x86_64 builds they were unused variables, failing clippy -D warnings in CI. * fix: restore bpv under cfg(aarch64), verify local clippy clean * fix: gate NEON test bindings behind cfg(aarch64) for x86_64 builds * fix: cfg-gate remaining NEON test bindings * fix: cfg-gate the NEON parity test at function level --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * ci: add release workflow (crates.io publish via tag) (#6) * chore: align .cora.yaml with current cora schema (#4) (#5) * chore: align .cora.yaml with current cora schema The old file used `review.enabled`, which the current cora binary rejects (unknown field), silently disabling pre-commit review. Mirrors the uteke .cora.yaml structure with vecq-specific rules (determinism, zero-dependency core). * fix: gate NEON-only bindings behind cfg(aarch64) bpv and q_rot are only used on the NEON path; on x86_64 builds they were unused variables, failing clippy -D warnings in CI. * fix: restore bpv under cfg(aarch64), verify local clippy clean * fix: gate NEON test bindings behind cfg(aarch64) for x86_64 builds * fix: cfg-gate remaining NEON test bindings * fix: cfg-gate the NEON parity test at function level --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * ci: add release workflow (crates.io publish via tag, uteke pattern) --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * chore: bump version to 0.1.1 for first crates.io release --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * ci: add cora AI code review workflow (parity with uteke) (#13) * ci: add cora AI code review workflow (parity with uteke) Runs codecoradev/cora-review-action@v1 on every PR targeting develop or main, posting AI review feedback using org CORA_* secrets, matching the uteke repo reference workflow. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> * chore: retrigger CI to verify cora review secrets Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> --------- Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * fix(ci): correct CLA bot exemption to match actual bot logins (#14) dependabot PR authors have user.login `dependabot[bot]`, not `app/dependabot`, so the old skip list never matched and the CLA job failed every dependabot PR. Switch to an exact allowlist of trusted bot logins (dependabot/renovate/github-actions); the legacy app/* forms stay as fallbacks. A substring [bot] match was rejected in review — it would exempt arbitrary third-party GitHub Apps. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * chore(deps): bump rand from 0.8.8 to 0.10.2 (#2) Bumps [rand](https://github.com/rust-random/rand) from 0.8.8 to 0.10.2. - [Release notes](https://github.com/rust-random/rand/releases) - [Changelog](https://github.com/rust-random/rand/blob/master/CHANGELOG.md) - [Commits](rust-random/rand@0.8.8...0.10.2) --- updated-dependencies: - dependency-name: rand dependency-version: 0.10.2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump actions/github-script from 7 to 9 (#3) Bumps [actions/github-script](https://github.com/actions/github-script) from 7 to 9. - [Release notes](https://github.com/actions/github-script/releases) - [Commits](actions/github-script@v7...v9) --- updated-dependencies: - dependency-name: actions/github-script dependency-version: '9' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(cora): raise review llm max_tokens to 16384 (#15) * chore(cora): raise review llm max_tokens to 16384 glm-5.3 is a reasoning model; on dependency-lockfile diffs the default 4096-token budget is exhausted during reasoning (finish_reason=length, content=null), which made the CI cora-review fallback SARIF fire on PRs #2/#3. 16384 leaves room for reasoning plus the verdict. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> * chore: retrigger CI Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> --------- Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * feat(core): keyed API — add_keyed/remove_keyed/tombstones (#10) (#16) Adds the keyed layer requested for incremental integrators (issue #10, unblocks the cora-code adoption audit): - add_keyed(key, v): insert-or-replace under a stable u64 key (usearch-style), returns the slot index - remove_keyed(key) -> bool: tombstones the slot; storage stays in place so slot indices remain stable until compact() - search_keyed(q, k): top-k by key, tombstones skipped - compact(): rebuilds in place, dropping tombstones (keys preserved, slot indices shift) - key_of/contains_key/slots/tombstones introspection helpers - len()/is_empty() now report live vectors - to_bytes() writes live slots only: tombstones are dropped on disk without disturbing in-memory slot indices. File format unchanged (v1.1); keys are an in-memory concern — persist key->slot mappings in your own metadata store. NEON4 batch scoring is untouched: tombstoned slots are still scored to keep batches dense, then filtered before entering the top-k heap, preserving bit-identical results. TDD: 7 new tests cover keyed search, replace, stability across remove/serialize, compaction, drained indexes, keyed adds after a file load, and dim-mismatch panics. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * feat(core): x86_64 AVX2 scoring path (parity with NEON, bit-identity tested) (#17) * feat(core): x86_64 AVX2 scoring path, bit-identical to scalar (#11) Adds an explicit AVX2 nibble-gather scoring path mirroring the NEON one, selected at runtime with is_x86_feature_detected! (AVX2 is not baseline on x86_64): - score_avx2: 8 lanes = 8 scalar buckets; per 8-byte block, lane j computes q[2b]*lut[lo_b] + q[2b+1]*lut[hi_b] (mul, mul, add — no FMA) and accumulates in block order, then the same pairwise-tree reduction — structurally identical to the scalar loop, so results are bit-identical - score_avx24: 4-vector batch sharing the q deinterleave - LUT gather via vgatherdps (scale 4, nibble indices); q even/odd deinterleave via shuffle_ps + vpermps fixup - search() dispatches to the AVX2 batch when available; score() dispatches per call Bit-identity is enforced by new tests (avx2_matches_scalar_bitwise, avx24_matches_avx2_bitwise, search dispatch == scalar) including a dim-8 case covering the 4-byte tail. The x86_64 CI job runs these on native AVX2 hardware (Rosetta hides AVX2 via CPUID, so local emulated runs cannot exercise the path). docs/BENCHMARK.md: per-architecture scoring-path table; x86_64 numbers explicitly pending native measurement, Rosetta excluded. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> * fix(clippy): iterate acc via enumerate in score_avx24 batch loop clippy 1.98 (CI stable) flags the 0..4 indexing loop under needless_range_loop; local 1.89 does not. Same semantics. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> --------- Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * docs: canonical SQLite BLOB storage pattern (#12) (#18) Adds docs/SQLITE.md: when to embed the index vs standalone file, the single-row and per-shard schema shapes, save/load with rusqlite in one transaction, atomicity notes (WAL + synchronous=NORMAL — no manual checkpoint choreography needed for correctness), measured save/load latencies at 1k/10k/50k vectors (dim 768, ~514 B/vec), and pitfalls (memory duplication on load, slot stability across save/reload interacting with the keyed API, churn-heavy workloads, embed size threshold, seed discipline). README links the page and mentions the per-architecture scoring-path matrix in BENCHMARK.md. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * chore: bump version to 0.2.0 (#19) Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * feat(core): Matryoshka-aware working_dim truncation (#30) * feat(core): Matryoshka-aware working_dim truncation (#24) Adds VecqIndex::with_working_dim(dim, working_dim, seed): quantize only the leading working_dim dimensions of dim-dimensional vectors, for Matryoshka-trained embedding models (EmbeddingGemma, text-embedding-3, ...). Truncation happens BEFORE normalization and rotation — RHDH mixes dimensions, so post-rotation truncation would not be Matryoshka-equivalent. - Callers always pass full-dim vectors/queries; the index truncates internally, keeping the add/search call sites unchanged - working_dim() accessor; dim() remains the caller-facing dim - Format v1.2: the previously-reserved u16 header field carries working_dim (0 = full dim); payload layout identical to v1.1. Readers accept v1, v1.1 and v1.2; writers emit v1.2 - README: Matryoshka recipe; BENCHMARK.md format note Tests (TDD, 6 new): working_dim == dim is bit-identical to new(); synthetic-Matryoshka data keeps neighbor ranking at ~1/3 storage; v1.2 round-trip preserves working_dim; legacy v1.1 files load bit-identically; working_dim > dim and 0 panic. Validated locally across repeated runs: native workspace suites 2x, x86_64 target, clippy -D warnings both targets, fmt, bench regression check. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> * fix(core): reject working_dim > u16::MAX unless equal to dim Cora CI review caught a real wrap: to_bytes casts working_dim to u16, so working_dim=70000 with dim=100000 wrote 4464 — a file that parses successfully with the wrong code layout (silent wrong search results), and working_dim=65536 wrapped to 0 (read as full dim). Construction now rejects working_dim > u16::MAX unless it equals dim (stored as 0 in the header). Regression tests for the panic case and for full-dim indexes with dim > u16::MAX. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> --------- Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * feat(core): keyed parity with usearch — relabel + multi-vectors-per-key (#26) (#33) - relabel(old_key, new_key) -> bool: renames a key in place (slots untouched); rejects unknown source / taken target, self-relabel is a successful no-op - add_keyed_multi(key, v): appends another vector under one key (usearch's multi mode); keys hold 1..n slots - remove_keyed(key): removes every slot of the key; remove_keyed_at(key, slot): removes one slot, shrinking the key back to the single-slot representation when one slot remains - search_keyed dedupes multi-slot keys (one entry per key, best slot's score), so results can hold fewer than k entries - compact rebuilds both single- and multi-key mappings Internals: single-slot keys stay in a HashMap<u64, usize>; multi keys move to HashMap<u64, Vec<usize>> — the common case remains allocation-free. append_slot no longer registers keys (caller-owned), fixing a double-map registration bug the tests caught in the promote path. Tests (TDD, 4 new): relabel semantics, multi add/search/dedupe, remove/remove_at lifecycle, multi replace + relabel + compact round trip. README usage updated. Validated locally per repo discipline: native workspace 5/5 x5 runs, x86_64 target 41/41, clippy -D warnings 0 findings both targets, fmt clean, bench numbers unchanged. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * bench: head-to-head vs TurboQuant and RaBitQ at 4 bits (#28) (#34) Adds bin/vs_quantizers: identical synthetic clustered datasets, exact f32 cosine ground truth, measuring recall@10 / ms-per-query / build time / bytes-per-vector for vecq vs TurboQuant-MSE 4-bit vs RaBitQ 4-bit brute force (rabitq-rs). TurboQuant is scanned SDC-style through a 16x16 product table built from OUR codebook instance (TurboQuantMSE::with_codebook) so the LUT is structurally guaranteed to match the encoder; the crate exposes no ADC path or rotation accessor. RaBitQ runs via its first-class BruteForceRabitqIndex, as implemented (internal rayon during train). Results (aarch64, single-threaded, recall deterministic across runs): vecq leads scan speed (2.1-2.7 vs 15.0-15.7 / 37.9-39.3 ms/q at n=10k dim=768) and recall at dim 768 (0.840 vs 0.798 / 0.827), with the honest caveat that competitors use ~25% less storage per vector (no per-vector scale, no power-of-two padding). Full tables + methodology notes + go/no-go for #22/#23 in docs/BENCHMARK.md. Competitor crates are bench-only dependencies; vecq-core stays zero-dependency. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * docs: add 0.2.0 changelog entry (#31) (#35) Backfills the v0.2.0 section (keyed API, AVX2 path, Matryoshka working_dim, SQLite guide, competitor benchmark, format v1.2, CLA bot fix) so the tag's user-facing changes are visible. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * fix(core): persist the keyed map — file format v1.3 (#32) (#36) Keyed state used to vanish on save/reload: from_bytes rebuilt codes and scales but never the key->slot map, so search_keyed/remove_keyed were dead on every reloaded index (user-filed repro in #32). Format v1.3 appends a keyed-slot table after the codes block: [entries u32][slot u32 + key u64 each]. Slot ids are dense positions among the serialized (alive) slots — matching the reader's slot space — not in-memory indices, which can exceed the serialized count when tombstones are dropped (caught by the multi-key round-trip test). Entries are validated (slot bounds, duplicate keys) and restore_keys rebuilds both the single- and multi-key maps, so reloaded indexes are fully keyed-capable (search_keyed, remove_keyed(_at), relabel, compact all work). Readers accept v1/v1.1/v1.2/v1.3; writers emit v1.3. docs (SQLITE.md, README, BENCHMARK.md) updated; CHANGELOG Unreleased entry added. Tests (TDD, 2 new): the issue's exact repro (keys survive reload, reloaded index remains keyed-capable) and a multi-key round trip with remove_keyed_at + compact + re-serialization stability. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * feat(core): cascade search — 2-bit prefilter + 4-bit rescore (#22) (#37) Adds an opt-in approximate search mode: enable_cascade() derives a 2-bit signature per slot from the stored nibbles (the two high bits, i.e. a coarse Lloyd re-quantization — padded/4 bytes per slot), and search_cascade(q, k, r) ranks slots by L1 distance between the query's and each slot's 2-bit codes (pure integer math, 16-entry pair LUT), keeps the r closest, and rescores those with the standard bit-identical 4-bit path. Design notes vs the original issue sketch: - 2-bit L1 instead of 1-bit Hamming: the Lloyd-Max codebook is not sign-symmetric (MSB of the code is a +0.164 threshold, not zero), so plain sign-bit Hamming degenerates on clustered data (measured 6/10 top-10 overlap at r=50 on n=1k). The 2-bit re-quantization keeps the derivation trivially consistent between database (nibble >> 2) and query (quantize_4bit >> 2 on the unnormalized rotated dims, via the new PreparedQuery::rnorm) while being strictly more discriminative (same measurement: 6/10 at r=50 but 1.00 at r=200; monotone). - No format change: signatures are derived from codes, not persisted — enable_cascade() must be called after from_bytes; add/replace/compact drop the signatures (documented). - Determinism: integer prefilter + tie-break toward smaller slots + bit-identical rescore; r >= live is exactly search() (tested bitwise). Tombstoned slots are skipped. Tests (TDD, 7 new): bitwise equivalence at r >= n, monotone recall in r on both a moderate and an adversarial clustered set, tombstone skipping + determinism, reload + compact behavior, empty index, r clamping, working_dim composition. README cascade recipe added. Local validation (repeated): native workspace 6/6 x5 runs, x86_64 50/50, clippy -D warnings 0/0, fmt clean, bench unchanged (0.35-0.38 ms/q baseline). Pre-commit cora review: no findings. Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * feat(core): residual quantization — opt-in recall mode, exact-norm two-term scoring, format v1.4 (#23) (#38) - Encode: second Lloyd-Max pass over the first-pass residual (format v1.4, readers accept v1-v3)\n- Scoring: two-term ADC with the EXACT reconstruction norm (cross term 2*rms*<d0,d1> + true <d1,d1> energy folded in at encode time; no format change, kernels untouched)\n- Real EmbeddingGemma: recall@1 0.990 / recall@10 0.984 at ~3x compression, 1.43x scan cost (plain: 0.910/0.958 @ 5.98x; usearch HNSW 0.995 @ 1x)\n- Adversarial clustered set: residual 0.87 vs plain 0.66 (was 0.58 with the approximate denominator)\n- real_residual_validation.rs (ignored, dataset-gated) + docs/BENCHMARK.md section\n- Re-tested & re-benchmarked before merge per policy: fmt/clippy clean, 54/54 tests debug+release, plain-path recall bit-identical baseline across real/vs_usearch/vs_quantizers * feat(core): configurable Lloyd-Max width (4/5/6-bit), default 5-bit sweet spot (#39) (#41) * feat(core): configurable Lloyd-Max width (4/5/6-bit), default 5-bit sweet spot (#39) - set_bits() width option, frozen after first add; default 5-bit (4.79x, recall@10 0.979 on real EmbeddingGemma) per locked design - LSB-first bit-packing with 16-bit RMW window (codes span byte boundaries at 5/6-bit); pack_code/unpack_code shared by encode and reference scoring - score_wide_scalar: portable per-width scoring via lloyd::centroids; 4-bit NEON path untouched (bit-identical, byte-identical files) - format v1.5: explicit width byte after header (plain non-4-bit only); 4-bit plain stays v1.3, residual v1.4; readers accept all - cascade search asserts 4-bit (signatures are nibble-based) - widths bench bin: end-to-end 4/5/6-bit + residual verification - tests: width matrix (B/vec, v1.3/v1.4/v1.5, round-trips), naive score parity at every width, wide-vs-residual recall dominance - README: configurable width, updated guarantees and format list * fix(test): AVX2 dispatch parity test covers all widths (#39) The x86_64-only test still referenced the 4-bit nibble path while the default width is now 5-bit; loop 4/5/6 with the width-matched scalar reference. Compile-checked for x86_64-unknown-linux-gnu. * perf(neon): batch-4 wide kernel for 5/6-bit scoring (#40) - score_neon_wide4: one u64 window per 8 dims replaces 8 unpack_code calls; centroids gathered through L1; NEON mul/add with per-lane bucket order identical to score_wide_scalar (bit-identity tested bitwise for 5/6-bit x dims {128,384}, incl. batch boundaries) - search dispatch: 4-bit LUT path and wide path share the batch loop; residual rescore unchanged (4-bit only) - x86_64 unchanged (scalar wide path; AVX2 wide kernel = follow-up) - E2E (real, d=768, n=2000): 5-bit 4.27 -> 3.23 ms/q; extraction is now the bottleneck — split-layout (nibble stream + vqtbl blend) is the documented next lever in #40 --------- Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * docs: benchmark width matrix (#39/#40) + changelog for Unreleased (#42) - BENCHMARK.md: results table gains the 5-bit default row; new width matrix section (4/5/6-bit + residual, post wide-kernel); analysis and limitations updated for the extraction-bound 5/6-bit path with the #40 ceiling analysis; conclusion reflects configurable width - CHANGELOG: Unreleased gains #23/#39/#40 entries Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * feat(core): zero-copy VecqView — serve an index straight from bytes (#25) (#43) - VecqView::from_bytes borrows v1.2+ file bytes (mmap, Box<[u8]>, any owner); no payload copying; keyed map absent by design, views are dense (to_bytes drops tombstones) - shared kernel dispatch extracted (score_raw_dispatch, score_batch4) so index and view hit identical kernels in identical order — bitwise parity tested at 4/5/6-bit, residual, and working_dim, plus malformed-input rejection incl. trailing keyed-table extent - view search uses the same batch-4 loop shape as the index (parity: 19.96 vs 19.85 ms/q warm at n=12k) - mmap cold-start harness (bench-only memmap2 dep; core stays zero-dependency): map+parse 64 us vs 4.9 ms full load (~76x faster time-to-ready, 12k vectors, 5-bit, 7.7 MB file) - docs/SQLITE.md: when to skip the BLOB — mmap view guidance Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * docs: README overhaul for the width/view era + stale-claim sweep (#44) - README: Modes table (4/5/6-bit + residual), zero-copy VecqView usage, Persistence & serving section, honest Performance paragraph for the default width, corrected Status (crates.io prepared, not published), Why-vecq table moved to default-width numbers - lib.rs module docs: configurable width, LSB-first packing, VecqView - BENCHMARK.md: dataset bullet names format v1.5 + 5-bit default - SQLITE.md: width-aware size formula, refreshed size table, VecqView pointer in the size section - CHANGELOG: #25 entry Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> * chore: bump version to 0.3.0 (#45) Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> --------- Signed-off-by: ajianaz <ajianaz@users.noreply.github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: ajianaz <ajianaz@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps actions/github-script from 7 to 9.
Release notes
Sourced from actions/github-script's releases.
... (truncated)
Commits
3a2844bMerge pull request #700 from actions/salmanmkc/expose-getoctokit + prepare re...ca10bbdfix: use@octokit/core/types import for v7 compatibility86e48e2merge: incorporate main branch changesc108472chore: rebuild dist for v9 upgrade and getOctokit factoryafff112Merge pull request #712 from actions/salmanmkc/deployment-false + fix user-ag...ff8117eci: fix user-agent test to handle orchestration ID81c6b78ci: use deployment: false to suppress deployment noise from integration tests3953cafdocs: update README examples from@v8to@v9, add getOctokit docs and v9 brea...c17d55bci: add getOctokit integration test joba047196test: add getOctokit integration tests via callAsyncFunction