fix: honest index readiness — no silently-empty queries on a cold index
Closes the "dishonest readiness proxy" anti-pattern (Pattern A): size()>0 /
isInitialized were treated as "this index serves queries", but a cold native
index can load its COUNT before its SERVING structure, so a query returned a
silent [] indistinguishable from "no such data". A shared assessIndexReadiness()
now reads only the provider's honest isReady() signal (never size()), applied at
every site:
- Vector: a one-shot verifyVectorLive() guard on the semantic/proximity search
path (a pure semantic find({query}) has no filter, so nothing guarded it). It
prefers isReady(), else a known-vector self-match probe; self-heals via rebuild
or throws the new VectorIndexNotReadyError instead of a silent [].
- Graph: getVerbsBySource/ByTarget skip the fast path when the provider reports
not-ready (falling to the canonical shard scan), plus a one-shot probe that
self-heals a no-isReady provider whose adjacency did not cold-load.
- getIndexStatus(): folds in per-index honest `ready` (making `populated`
honest) + rebuildFailed/rebuildError/degradedIds, so a readiness probe never
200s a brain that is still warming up or degraded.
Unblocked by the native providers now reporting serving-truth (graph via
SSTable-residency readiness, vector via durableBaseLoadFailed). New export:
VectorIndexNotReadyError. getIndexStatus gains additive fields. No breaking API.
13 new tests; existing readiness guards green.
This commit is contained in:
parent
36d4e80ba2
commit
d0f69c731f
9 changed files with 654 additions and 9 deletions
33
RELEASES.md
33
RELEASES.md
|
|
@ -10,6 +10,39 @@ Full auto-generated changelog: `CHANGELOG.md` · Releases: https://github.com/so
|
|||
|
||||
---
|
||||
|
||||
## v8.2.8 — 2026-07-13 (honest index readiness — no more silently-empty queries on a cold index)
|
||||
|
||||
Closes the last of the three spine anti-patterns: the "dishonest readiness proxy," where `size() > 0`
|
||||
was treated as "this index actually serves queries." On a cold open (fresh boot, restart, crash
|
||||
recovery) a native index can load its **count** before its **serving structure** — so for a brief
|
||||
window it has data but cannot answer, and a query returned a silent empty result indistinguishable
|
||||
from "no such data." Every fix here asks the index whether it can *actually serve*, and if not,
|
||||
self-heals or fails loudly instead of returning `[]`.
|
||||
|
||||
- **Semantic search no longer returns a silent `[]` on a cold vector index.** A pure semantic
|
||||
`find({ query })` has no filter, so nothing previously guarded the vector index. A new one-shot
|
||||
guard verifies the vector index serves a known persisted vector on the first semantic/proximity
|
||||
search — preferring the provider's honest `isReady()` signal, else a known-vector self-match probe.
|
||||
It rebuilds from canonical records if the serving structure did not load, and throws the new
|
||||
**`VectorIndexNotReadyError`** only if a rebuild still cannot serve — never a silent empty result.
|
||||
|
||||
- **Relationship reads fall back to the canonical scan instead of an empty result on a cold graph
|
||||
index.** `getVerbsBySource`/`getVerbsByTarget` (used by relationship queries and virtual-filesystem
|
||||
traversal) skipped the fast path only on `isInitialized` — which reads true once the manifest loaded
|
||||
even if the source→target adjacency did not. They now consult the honest readiness signal and, when
|
||||
the adjacency is not serving, take the correct-but-slower canonical shard scan. A one-shot self-heal
|
||||
probe covers providers that expose no readiness signal.
|
||||
|
||||
- **`getIndexStatus()` tells the truth for readiness probes.** It reported `populated: size>0` only, so
|
||||
a Kubernetes readiness check could route traffic to a brain still warming up. It now folds in the
|
||||
honest per-index `ready` signal (making `populated` honest), plus the degraded states already
|
||||
surfaced by `checkHealth()`/`validateIndexConsistency()` (`rebuildFailed`/`rebuildError` and a
|
||||
`degradedIds` count) — so a probe never reports 200-ready over a known-degraded index.
|
||||
|
||||
This completes the write/index-spine hardening end to end. New export: **`VectorIndexNotReadyError`**;
|
||||
`getIndexStatus()` gains additive fields (`rebuildFailed`, `rebuildError?`, `degradedIds`, per-index
|
||||
`ready?`). No breaking API change. Each fix ships with a dedicated regression test.
|
||||
|
||||
## v8.2.7 — 2026-07-13 (loadBinaryBlob fault-propagation — the lockstep completion of 8.2.6)
|
||||
|
||||
Completes the Pass-1 spine hardening. `loadBinaryBlob` (the raw-blob read a native accelerator mmaps
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue